]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OptionRomPkg: Added bus driver for FTDI USB to serial adapters
authorAshley DeSimone <ashley.e.desimone@intel.com>
Tue, 29 Oct 2013 17:46:03 +0000 (17:46 +0000)
committerashdesimone <ashdesimone@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 29 Oct 2013 17:46:03 +0000 (17:46 +0000)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ashley DeSimone <ashley.e.desimone@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14817 6f19259b-4bc3-4df7-8a09-765794883524

OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/CompatibleDevices.txt [new file with mode: 0644]
OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/ComponentName.c [new file with mode: 0644]
OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.c [new file with mode: 0644]
OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.h [new file with mode: 0644]
OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDxe.inf [new file with mode: 0644]
OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/ReadMe.txt [new file with mode: 0644]
OptionRomPkg/OptionRomPkg.dsc

diff --git a/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/CompatibleDevices.txt b/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/CompatibleDevices.txt
new file mode 100644 (file)
index 0000000..1ec1cce
--- /dev/null
@@ -0,0 +1,5 @@
+The following devices have been confirmed to work with the USB Serial Driver:\r
+\r
+Brand        Model Name        Product Name          Vendor ID    Device ID\r
+Gearmo       USA_FTDI-36       USB to RS-232         0x0403       0x6001\r
+Sabrent      CB-FTDI                                 0x0403       0x6001
\ No newline at end of file
diff --git a/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/ComponentName.c b/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/ComponentName.c
new file mode 100644 (file)
index 0000000..c200878
--- /dev/null
@@ -0,0 +1,224 @@
+/** @file\r
+  UEFI Component Name(2) protocol implementation for USB Serial driver.\r
+\r
+Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD\r
+License which accompanies this distribution.  The full text of the license may\r
+be found at http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "FtdiUsbSerialDriver.h"\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gUsbSerialComponentName = {\r
+  (EFI_COMPONENT_NAME_GET_DRIVER_NAME) UsbSerialComponentNameGetDriverName,\r
+  (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) UsbSerialComponentNameGetControllerName,\r
+  "eng"\r
+};\r
+\r
+//\r
+// EFI Component Name 2 Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gUsbSerialComponentName2 = {\r
+  UsbSerialComponentNameGetDriverName,\r
+  UsbSerialComponentNameGetControllerName,\r
+  "en"\r
+};\r
+\r
+//\r
+// Driver name string table\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mUsbSerialDriverNameTable[] = {\r
+  { "eng;en", L"FTDI-232 USB Serial Driver" },\r
+  { NULL , NULL }\r
+};\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language,\r
+  then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This                  A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+  @param  Language              A pointer to a Null-terminated ASCII string\r
+                                array indicating the language. This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified\r
+                                in RFC 4646 or ISO 639-2 language code format.\r
+  @param  DriverName            A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                driver specified by This in the language\r
+                                specified by Language.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by\r
+                                This and the language specified by Language was\r
+                                returned in DriverName.\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbSerialComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,\r
+  IN  CHAR8                         *Language,\r
+  OUT CHAR16                        **DriverName\r
+  )\r
+{\r
+  return LookupUnicodeString2 (\r
+           Language,\r
+           This->SupportedLanguages,\r
+           mUsbSerialDriverNameTable,\r
+           DriverName,\r
+           (BOOLEAN)(This == &gUsbSerialComponentName2)\r
+           );\r
+}\r
+\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified by\r
+  Language, then a pointer to the controller name is returned in ControllerName,\r
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently\r
+  managing the controller specified by ControllerHandle and ChildHandle,\r
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not\r
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This                  A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+  @param  ControllerHandle      The handle of a controller that the driver\r
+                                specified by This is managing.  This handle\r
+                                specifies the controller whose name is to be\r
+                                returned.\r
+  @param  ChildHandle           The handle of the child controller to retrieve\r
+                                the name of.  This is an optional parameter that\r
+                                may be NULL.  It will be NULL for device\r
+                                drivers.  It will also be NULL for a bus drivers\r
+                                that wish to retrieve the name of the bus\r
+                                controller.  It will not be NULL for a bus\r
+                                driver that wishes to retrieve the name of a\r
+                                child controller.\r
+  @param  Language              A pointer to a Null-terminated ASCII string\r
+                                array indicating the language.  This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified in\r
+                                RFC 4646 or ISO 639-2 language code format.\r
+  @param  ControllerName        A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                controller specified by ControllerHandle and\r
+                                ChildHandle in the language specified by\r
+                                Language from the point of view of the driver\r
+                                specified by This.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in\r
+                                the language specified by Language for the\r
+                                driver specified by This was returned in\r
+                                DriverName.\r
+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+                                EFI_HANDLE.\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently\r
+                                managing the controller specified by\r
+                                ControllerHandle and ChildHandle.\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbSerialComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                    ControllerHandle,\r
+  IN  EFI_HANDLE                    ChildHandle      OPTIONAL,\r
+  IN  CHAR8                         *Language,\r
+  OUT CHAR16                        **ControllerName\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  USB_SER_DEV             *UsbSerDev;\r
+  EFI_SERIAL_IO_PROTOCOL  *SerialIo;\r
+  EFI_USB_IO_PROTOCOL     *UsbIoProtocol;\r
+  \r
+  //\r
+  // This is a device driver, so ChildHandle must be NULL.\r
+  //\r
+  if (ChildHandle != NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Check Controller's handle\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiUsbIoProtocolGuid,\r
+                  (VOID **) &UsbIoProtocol,\r
+                  gUsbSerialDriverBinding.DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    gBS->CloseProtocol (\r
+           ControllerHandle,\r
+           &gEfiUsbIoProtocolGuid,\r
+           gUsbSerialDriverBinding.DriverBindingHandle,\r
+           ControllerHandle\r
+           );\r
+\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (Status != EFI_ALREADY_STARTED) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  //\r
+  // Get the device context\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiSerialIoProtocolGuid,\r
+                  (VOID **) &SerialIo,\r
+                  gUsbSerialDriverBinding.DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  UsbSerDev = USB_SER_DEV_FROM_THIS (SerialIo);\r
+\r
+  return LookupUnicodeString2 (\r
+           Language,\r
+           This->SupportedLanguages,\r
+           UsbSerDev->ControllerNameTable,\r
+           ControllerName,\r
+           (BOOLEAN)(This == &gUsbSerialComponentName2)\r
+           );\r
+}\r
diff --git a/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.c b/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.c
new file mode 100644 (file)
index 0000000..595ef4a
--- /dev/null
@@ -0,0 +1,2588 @@
+/** @file\r
+  USB Serial Driver that manages USB to Serial and produces Serial IO Protocol.\r
+\r
+Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.\r
+Portions Copyright 2012 Ashley DeSimone\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD\r
+License which accompanies this distribution.  The full text of the license may\r
+be found at http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+//\r
+\r
+// Tested with VEND_ID 0x0403, DEVICE_ID 0x6001\r
+//\r
+// Driver starts the device with the following values:\r
+// 115200, No parity, 8 data bits, 1 stop bit, No Flow control\r
+//\r
+\r
+#include "FtdiUsbSerialDriver.h"\r
+\r
+//\r
+// Table of supported devices. This is the device information that this\r
+// driver was developed with. Add other FTDI devices as needed.\r
+//\r
+USB_DEVICE gUSBDeviceList[] = {\r
+  {VID_FTDI, DID_FTDI_FT232},\r
+  {0,0}\r
+};\r
+\r
+//\r
+// USB Serial Driver Global Variables\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL  gUsbSerialDriverBinding = {\r
+  UsbSerialDriverBindingSupported,\r
+  UsbSerialDriverBindingStart,\r
+  UsbSerialDriverBindingStop,\r
+  0xa,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+//\r
+// Table with the nearest power of 2 for the numbers 0-15\r
+//\r
+UINT8 gRoundedPowersOf2[16] = { 0, 2, 2, 4, 4, 4, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16 };\r
+\r
+/**\r
+  Check to see if the device path node is the Flow control node\r
+\r
+  @param[in] FlowControl    The device path node to be checked\r
+\r
+  @retval    TRUE           It is the flow control node\r
+  @retval    FALSE          It is not the flow control node\r
+\r
+**/\r
+BOOLEAN\r
+IsUartFlowControlNode (\r
+  IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl\r
+  )\r
+{\r
+  return (BOOLEAN) (\r
+           (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) &&\r
+           (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) &&\r
+           (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid))\r
+           );\r
+}\r
+\r
+/**\r
+  Checks the device path to see if it contains flow control.\r
+\r
+  @param[in] DevicePath    The device path to be checked\r
+\r
+  @retval    TRUE          It contains flow control\r
+  @retval    FALSE         It does not contain flow control\r
+\r
+**/\r
+BOOLEAN\r
+ContainsFlowControl (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+  )\r
+{\r
+  while (!IsDevicePathEnd (DevicePath)) {\r
+    if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) {\r
+      return TRUE;\r
+    }\r
+    DevicePath = NextDevicePathNode (DevicePath);\r
+  }\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Transfer the data between the device and host.\r
+\r
+  This function transfers the data between the device and host.\r
+  BOT transfer is composed of three phases: Command, Data, and Status.\r
+  This is the Data phase.\r
+\r
+  @param  UsbBot[in]                     The USB BOT device\r
+  @param  DataDir[in]                    The direction of the data\r
+  @param  Data[in, out]                  The buffer to hold data\r
+  @param  TransLen[in, out]              The expected length of the data\r
+  @param  Timeout[in]                    The time to wait the command to complete\r
+\r
+  @retval EFI_SUCCESS                    The data is transferred\r
+  @retval EFI_SUCCESS                    No data to transfer\r
+  @retval EFI_NOT_READY                  The device return NAK to the transfer\r
+  @retval Others                         Failed to transfer data\r
+\r
+**/\r
+EFI_STATUS\r
+UsbSerialDataTransfer (\r
+  IN USB_SER_DEV             *UsbBot,\r
+  IN EFI_USB_DATA_DIRECTION  DataDir,\r
+  IN OUT VOID                *Data,\r
+  IN OUT UINTN               *TransLen,\r
+  IN UINT32                  Timeout\r
+  )\r
+{\r
+  EFI_USB_ENDPOINT_DESCRIPTOR  *Endpoint;\r
+  EFI_STATUS                   Status;\r
+  UINT32                       Result;\r
+\r
+  //\r
+  // If no data to transfer, just return EFI_SUCCESS.\r
+  //\r
+  if ((DataDir == EfiUsbNoData) || (*TransLen == 0)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Select the endpoint then issue the transfer\r
+  //\r
+  if (DataDir == EfiUsbDataIn) {\r
+    Endpoint = &UsbBot->InEndpointDescriptor;\r
+  } else {\r
+    Endpoint = &UsbBot->OutEndpointDescriptor;\r
+  }\r
+\r
+  Result = 0;\r
+  Status = UsbBot->UsbIo->UsbBulkTransfer (\r
+                            UsbBot->UsbIo,\r
+                            Endpoint->EndpointAddress,\r
+                            Data,\r
+                            TransLen,\r
+                            Timeout,\r
+                            &Result\r
+                            );\r
+  if (EFI_ERROR (Status)) {\r
+    if (USB_IS_ERROR (Result, EFI_USB_ERR_NAK)) {\r
+      Status = EFI_NOT_READY;\r
+    } else {\r
+      UsbBot->Shutdown = TRUE; // Fixes infinite loop in older EFI\r
+    }\r
+    return Status;\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Sets the status values of the Usb Serial Device.\r
+\r
+  @param  UsbSerialDevice[in]  Handle to the Usb Serial Device to set the status\r
+                               for\r
+  @param  StatusBuffer[in]     Buffer holding the status values\r
+\r
+  @retval EFI_SUCCESS          The status values were read and set correctly\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetStatusInternal (\r
+  IN USB_SER_DEV  *UsbSerialDevice,\r
+  IN UINT8        *StatusBuffer\r
+  )\r
+{\r
+  UINT8  Msr;\r
+\r
+  Msr = (StatusBuffer[0] & MSR_MASK);\r
+\r
+  //\r
+  // set the Status values to disabled\r
+  //\r
+  UsbSerialDevice->StatusValues.CtsState = FALSE;\r
+  UsbSerialDevice->StatusValues.DsrState = FALSE;\r
+  UsbSerialDevice->StatusValues.RiState  = FALSE;\r
+  UsbSerialDevice->StatusValues.SdState  = FALSE;\r
+\r
+  //\r
+  // Check the values from the status buffer and set the appropriate status\r
+  // values to enabled\r
+  //\r
+  if ((Msr & CTS_MASK) == CTS_MASK) {\r
+    UsbSerialDevice->StatusValues.CtsState = TRUE;\r
+  }\r
+  if ((Msr & DSR_MASK) == DSR_MASK) {\r
+    UsbSerialDevice->StatusValues.DsrState = TRUE;\r
+  }\r
+  if ((Msr & RI_MASK) == RI_MASK) {\r
+    UsbSerialDevice->StatusValues.RiState = TRUE;\r
+  }\r
+  if ((Msr & SD_MASK) == SD_MASK) {\r
+    UsbSerialDevice->StatusValues.SdState = TRUE;\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Initiates a read operation on the Usb Serial Device.\r
+\r
+  @param  UsbSerialDevice[in]        Handle to the USB device to read\r
+  @param  BufferSize[in, out]        On input, the size of the Buffer. On output,\r
+                                     the amount of data returned in Buffer.\r
+                                     Setting this to zero will initiate a read\r
+                                     and store all data returned in the internal\r
+                                     buffer.\r
+  @param  Buffer [out]               The buffer to return the data into.\r
+\r
+  @retval EFI_SUCCESS                The data was read.\r
+  @retval EFI_DEVICE_ERROR           The device reported an error.\r
+  @retval EFI_TIMEOUT                The data write was stopped due to a timeout.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ReadDataFromUsb (\r
+  IN USB_SER_DEV  *UsbSerialDevice,\r
+  IN OUT UINTN    *BufferSize,\r
+  OUT VOID        *Buffer\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       ReadBufferSize;\r
+  UINT8       *ReadBuffer;\r
+  UINTN       Index;\r
+  EFI_TPL     Tpl;\r
+  UINT8       StatusBuffer[2]; // buffer to store the status bytes\r
+\r
+  ReadBufferSize = 512;\r
+  ReadBuffer     = &(UsbSerialDevice->ReadBuffer[0]);\r
+\r
+  if (UsbSerialDevice->Shutdown) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+  Status = UsbSerialDataTransfer (\r
+             UsbSerialDevice,\r
+             EfiUsbDataIn,\r
+             ReadBuffer,\r
+             &ReadBufferSize,\r
+             FTDI_TIMEOUT*2  //Padded because timers won't be exactly aligned\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->RestoreTPL (Tpl);\r
+    if (Status == EFI_TIMEOUT) {\r
+      return EFI_TIMEOUT;\r
+    } else {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Store the status bytes in the status buffer\r
+  //\r
+  for (Index = 0; Index < 2; Index++) {//only the first 2 bytes are status bytes\r
+    StatusBuffer[Index] = ReadBuffer[Index];\r
+  }\r
+  //\r
+  // update the statusvalue field of the usbserialdevice\r
+  //\r
+  Status = SetStatusInternal (UsbSerialDevice, StatusBuffer);\r
+  if (Status != EFI_SUCCESS) {\r
+  }\r
+\r
+  //\r
+  // Store the read data in the read buffer, start at 2 to ignore status bytes\r
+  //\r
+  for (Index = 2; Index < ReadBufferSize; Index++) {\r
+    if (((UsbSerialDevice->DataBufferTail + 1) % SW_FIFO_DEPTH) == UsbSerialDevice->DataBufferHead) {\r
+      break;\r
+    }\r
+    if (ReadBuffer[Index] == 0x00) {\r
+      //\r
+      // This is null, do not add\r
+      //\r
+    } else {\r
+      UsbSerialDevice->DataBuffer[UsbSerialDevice->DataBufferTail] = ReadBuffer[Index];\r
+      UsbSerialDevice->DataBufferTail = (UsbSerialDevice->DataBufferTail + 1) % SW_FIFO_DEPTH;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Read characters out of the buffer to satisfy caller's request.\r
+  //\r
+  for (Index = 0; Index < *BufferSize; Index++) {\r
+    if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {\r
+      break;\r
+    }\r
+    //\r
+    // Still have characters in the buffer to return\r
+    //\r
+    ((UINT8 *)Buffer)[Index]        = UsbSerialDevice->DataBuffer[UsbSerialDevice->DataBufferHead];\r
+    UsbSerialDevice->DataBufferHead = (UsbSerialDevice->DataBufferHead + 1) % SW_FIFO_DEPTH;\r
+  }\r
+  //\r
+  // Return actual number of bytes returned.\r
+  //\r
+  *BufferSize = Index;\r
+  gBS->RestoreTPL (Tpl);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Sets the initial status values of the Usb Serial Device by reading the status\r
+  bytes from the device.\r
+\r
+  @param  UsbSerialDevice[in]  Handle to the Usb Serial Device that needs its\r
+                               initial status values set\r
+\r
+  @retval EFI_SUCCESS          The status bytes were read successfully and the\r
+                               initial status values were set correctly\r
+  @retval EFI_TIMEOUT          The read of the status bytes was stopped due to a\r
+                               timeout\r
+  @retval EFI_DEVICE_ERROR     The device reported an error during the read of\r
+                               the status bytes\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetInitialStatus (\r
+  IN USB_SER_DEV          *UsbSerialDevice\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+  UINTN           BufferSize;\r
+  EFI_TPL         Tpl;\r
+  UINT8           StatusBuffer[2];\r
+\r
+  Status          = EFI_UNSUPPORTED;\r
+  BufferSize      = sizeof (StatusBuffer);\r
+\r
+  if (UsbSerialDevice->Shutdown) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+  Status = UsbSerialDataTransfer (\r
+             UsbSerialDevice,\r
+             EfiUsbDataIn,\r
+             StatusBuffer,\r
+             &BufferSize,\r
+             40    //Slightly more than 2x the FTDI polling frequency to make sure that data will be returned\r
+             );\r
+\r
+  Status = SetStatusInternal (UsbSerialDevice, StatusBuffer);\r
+\r
+  gBS->RestoreTPL (Tpl);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  UsbSerialDriverCheckInput.\r
+  attempts to read data in from the device periodically, stores any read data\r
+  and updates the control attributes.\r
+\r
+  @param  Event[in]\r
+  @param  Context[in]....The current instance of the USB serial device\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+UsbSerialDriverCheckInput (\r
+  IN  EFI_EVENT  Event,\r
+  IN  VOID       *Context\r
+  )\r
+{\r
+  UINTN        BufferSize;\r
+  USB_SER_DEV  *UsbSerialDevice;\r
+\r
+  UsbSerialDevice = (USB_SER_DEV*)Context;\r
+\r
+  if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {\r
+    //\r
+    // Data buffer is empty, try to read from device\r
+    //\r
+    BufferSize = 0;\r
+    ReadDataFromUsb (UsbSerialDevice, &BufferSize, NULL);\r
+    if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {\r
+      //\r
+      // Data buffer still has no data, set the EFI_SERIAL_INPUT_BUFFER_EMPTY\r
+      // flag\r
+      //\r
+      UsbSerialDevice->ControlBits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;\r
+    } else {\r
+      //\r
+      // Read has returned some data, clear the EFI_SERIAL_INPUT_BUFFER_EMPTY\r
+      // flag\r
+      //\r
+      UsbSerialDevice->ControlBits &= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY);\r
+    }\r
+  } else {\r
+    //\r
+    // Data buffer has data, no read attempt required\r
+    //\r
+    UsbSerialDevice->ControlBits &= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY);\r
+  }\r
+}\r
+\r
+/**\r
+  Encodes the baud rate into the format expected by the Ftdi device.\r
+\r
+  @param  BaudRate[in]                The baudrate to be set on the device\r
+  @param  EncodedBaudRate[out]        The baud rate encoded in the format\r
+                                      expected by the Ftdi device\r
+\r
+  @return EFI_SUCCESS                 Baudrate encoding was calculated\r
+                                      successfully\r
+  @return EFI_INVALID_PARAMETER       An invalid value of BaudRate was received\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EncodeBaudRateForFtdi (\r
+  IN  UINT64  BaudRate,\r
+  OUT UINT16  *EncodedBaudRate\r
+  )\r
+{\r
+  UINT32 Divisor;\r
+  UINT32 AdjustedFrequency;\r
+  UINT16 Result;\r
+\r
+  //\r
+  // Check to make sure we won't get an integer overflow\r
+  //\r
+  if ((BaudRate < 178) || ( BaudRate > ((FTDI_UART_FREQUENCY * 100) / 97))) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Baud Rates of 2000000 and 3000000 are special cases\r
+  //\r
+  if ((BaudRate >= FTDI_SPECIAL_CASE_300_MIN) && (BaudRate <= FTDI_SPECIAL_CASE_300_MAX)) {\r
+    *EncodedBaudRate = 0;\r
+    return EFI_SUCCESS;\r
+  }\r
+  if ((BaudRate >= FTDI_SPECIAL_CASE_200_MIN) && (BaudRate <= FTDI_SPECIAL_CASE_200_MAX)) {\r
+    *EncodedBaudRate = 1;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Compute divisor\r
+  //\r
+  Divisor = (FTDI_UART_FREQUENCY << 4) / (UINT32)BaudRate;\r
+\r
+  //\r
+  // Round the last 4 bits to the nearest power of 2\r
+  //\r
+  Divisor = (Divisor & ~(0xF)) + (gRoundedPowersOf2[Divisor & 0xF]);\r
+\r
+  //\r
+  // Check to make sure computed divisor is within \r
+  // the min and max that FTDI controller will accept\r
+  //\r
+  if (Divisor < FTDI_MIN_DIVISOR) {\r
+    Divisor = FTDI_MIN_DIVISOR;\r
+  } else if (Divisor > FTDI_MAX_DIVISOR) {\r
+    Divisor = FTDI_MAX_DIVISOR;\r
+  }\r
+\r
+  //\r
+  // Check to make sure the frequency that the FTDI chip will need to\r
+  // generate to attain the requested Baud Rate is within 3% of the\r
+  // 3MHz clock frequency that the FTDI chip runs at.\r
+  //\r
+  // (3MHz * 1600) / 103 = 46601941\r
+  // (3MHz * 1600) / 97  = 49484536\r
+  //\r
+  AdjustedFrequency = (((UINT32)BaudRate) * Divisor);\r
+  if ((AdjustedFrequency < FTDI_MIN_FREQUENCY) || (AdjustedFrequency > FTDI_MAX_FREQUENCY)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Encode the Divisor into the format FTDI expects\r
+  //\r
+  Result = (UINT16)(Divisor >> 4);\r
+  if ((Divisor & 0x8) != 0) {\r
+    Result |= 0x4000;\r
+  } else if ((Divisor & 0x4) != 0) {\r
+    Result |= 0x8000;\r
+  } else if ((Divisor & 0x2) != 0) {\r
+    Result |= 0xC000;\r
+  }\r
+\r
+  *EncodedBaudRate = Result;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Uses USB I/O to check whether the device is a USB Serial device.\r
+\r
+  @param  UsbIo[in]    Pointer to a USB I/O protocol instance.\r
+\r
+  @retval TRUE         Device is a USB Serial device.\r
+  @retval FALSE        Device is a not USB Serial device.\r
+\r
+**/\r
+BOOLEAN\r
+IsUsbSerial (\r
+  IN  EFI_USB_IO_PROTOCOL  *UsbIo\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_USB_DEVICE_DESCRIPTOR  DeviceDescriptor;\r
+  CHAR16                     *StrMfg;\r
+  BOOLEAN                    Found;\r
+  UINT32                     Index;\r
+\r
+  //\r
+  // Get the default device descriptor\r
+  //\r
+  Status = UsbIo->UsbGetDeviceDescriptor (\r
+                    UsbIo,\r
+                    &DeviceDescriptor\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  Found = FALSE;\r
+  Index = 0;\r
+  while (gUSBDeviceList[Index].VendorId != 0 &&\r
+         gUSBDeviceList[Index].DeviceId != 0 &&\r
+         !Found                                  ) {\r
+    if (DeviceDescriptor.IdProduct == gUSBDeviceList[Index].DeviceId &&\r
+        DeviceDescriptor.IdVendor  == gUSBDeviceList[Index].VendorId      ){\r
+        //\r
+        // Checks to see if a string descriptor can be pulled from the device in\r
+        // the selected language. If not False is returned indicating that this\r
+        // is not a Usb Serial Device that can be managegd by this driver\r
+        //\r
+        StrMfg = NULL;\r
+        Status = UsbIo->UsbGetStringDescriptor (\r
+                          UsbIo,\r
+                          USB_US_LANG_ID, // LANGID selector, should make this\r
+                                          // more robust to verify lang support\r
+                                          // for device\r
+                          DeviceDescriptor.StrManufacturer,\r
+                          &StrMfg\r
+                          );\r
+        if (StrMfg != NULL) {\r
+          FreePool (StrMfg);\r
+        }\r
+        if (EFI_ERROR (Status)) {\r
+          return FALSE;\r
+        }\r
+        return TRUE;\r
+    }\r
+    Index++;\r
+  }\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Internal function that sets the Data Bits, Stop Bits and Parity values on the\r
+  Usb Serial Device with a single usb control transfer.\r
+\r
+  @param  UsbIo[in]                  Usb Io Protocol instance pointer\r
+  @param  DataBits[in]               The data bits value to be set on the Usb\r
+                                     Serial Device\r
+  @param  Parity[in]                 The parity type that will be set on the Usb\r
+                                     Serial Device\r
+  @param  StopBits[in]               The stop bits type that will be set on the\r
+                                     Usb Serial Device\r
+  @param  LastSettings[in]           A pointer to the Usb Serial Device's\r
+                                     PREVIOUS_ATTRIBUTES item\r
+\r
+  @retval EFI_SUCCESS                The data items were correctly set on the\r
+                                     USB Serial Device\r
+  @retval EFI_INVALID_PARAMETER      An invalid data parameter or an invalid\r
+                                     combination or parameters was used\r
+  @retval EFI_DEVICE_ERROR           The device is not functioning correctly and\r
+                                     the data values were unable to be set\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetDataInternal (\r
+  IN EFI_USB_IO_PROTOCOL  *UsbIo,\r
+  IN UINT8                DataBits,\r
+  IN EFI_PARITY_TYPE      Parity,\r
+  IN EFI_STOP_BITS_TYPE   StopBits,\r
+  IN PREVIOUS_ATTRIBUTES  *LastSettings\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_USB_DEVICE_REQUEST  DevReq;\r
+  UINT32                  ReturnValue;\r
+  UINT8                   ConfigurationValue;\r
+\r
+  //\r
+  // Since data bits settings of 6,7,8 cannot be set with a stop bits setting of\r
+  // 1.5 check to see if this happens when the values of last settings are used\r
+  //\r
+  if ((DataBits == 0) && (StopBits == OneFiveStopBits)) {\r
+    if ((LastSettings->DataBits == 6) || (LastSettings->DataBits == 7) || (LastSettings->DataBits == 8)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  } else if ((StopBits == DefaultStopBits) && ((DataBits == 6) || (DataBits == 7) || (DataBits == 8))) {\r
+    if (LastSettings->StopBits == OneFiveStopBits) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  } else if ((DataBits == 0) && (StopBits == DefaultStopBits)) {\r
+    if (LastSettings->StopBits == OneFiveStopBits) {\r
+      if ((LastSettings->DataBits == 6) || (LastSettings->DataBits == 7) || (LastSettings->DataBits == 8)) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // set the DevReq.Value for the usb control transfer to the correct value\r
+  // based on the seleceted number of data bits if there is an invalid number of\r
+  // data bits requested return EFI_INVALID_PARAMETER\r
+  //\r
+  if (((DataBits < 5 ) || (DataBits > 8)) && (DataBits != 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (DataBits == 0) {\r
+    //\r
+    // use the value of LastDataBits\r
+    //\r
+    DevReq.Value = SET_DATA_BITS (LastSettings->DataBits);\r
+  } else {\r
+    //\r
+    // use the value of DataBits\r
+    //\r
+    DevReq.Value = SET_DATA_BITS (DataBits);\r
+  }\r
+\r
+  //\r
+  // Set Parity\r
+  //\r
+  if (Parity == DefaultParity) {\r
+    Parity = LastSettings->Parity;\r
+  }\r
+\r
+  if (Parity == NoParity) {\r
+    DevReq.Value |= SET_PARITY_NONE;\r
+  } else if (Parity == EvenParity) {\r
+    DevReq.Value |= SET_PARITY_EVEN;\r
+  } else if (Parity == OddParity){\r
+    DevReq.Value |= SET_PARITY_ODD;\r
+  } else if (Parity == MarkParity) {\r
+    DevReq.Value |= SET_PARITY_MARK;\r
+  } else if (Parity == SpaceParity) {\r
+    DevReq.Value |= SET_PARITY_SPACE;\r
+  }\r
+\r
+  //\r
+  // Set Stop Bits\r
+  //\r
+  if (StopBits == DefaultStopBits) {\r
+    StopBits = LastSettings->StopBits;\r
+  }\r
+\r
+  if (StopBits == OneStopBit) {\r
+    DevReq.Value |= SET_STOP_BITS_1;\r
+  } else if (StopBits == OneFiveStopBits) {\r
+    DevReq.Value |= SET_STOP_BITS_15;\r
+  } else if (StopBits == TwoStopBits) {\r
+    DevReq.Value |= SET_STOP_BITS_2;\r
+  }\r
+\r
+  //\r
+  // set the rest of the DevReq parameters and perform the usb control transfer\r
+  // to set the data bits on the device\r
+  //\r
+  DevReq.Request     = FTDI_COMMAND_SET_DATA;\r
+  DevReq.RequestType = USB_REQ_TYPE_VENDOR;\r
+  DevReq.Index       = FTDI_PORT_IDENTIFIER;\r
+  DevReq.Length      = 0; // indicates that there is no data phase in this request\r
+\r
+  Status = UsbIo->UsbControlTransfer (\r
+                    UsbIo,\r
+                    &DevReq,\r
+                    EfiUsbDataOut,\r
+                    WDR_SHORT_TIMEOUT,\r
+                    &ConfigurationValue,\r
+                    1,\r
+                    &ReturnValue\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    goto StatusError;\r
+  }\r
+  return Status;\r
+\r
+StatusError:\r
+  if ((Status != EFI_INVALID_PARAMETER) || (Status != EFI_DEVICE_ERROR)) {\r
+    return EFI_DEVICE_ERROR;\r
+  } else {\r
+    return Status;\r
+  }\r
+}\r
+\r
+/**\r
+  Internal function that sets the baudrate on the Usb Serial Device.\r
+\r
+  @param  UsbIo[in]                  Usb Io Protocol instance pointer\r
+  @param  BaudRate[in]               The baudrate value to be set on the device.\r
+                                     If this value is 0 the value of LastBaudRate\r
+                                     will be used instead\r
+  @param  LastBaudRate[in]           The baud rate value that was previously set\r
+                                     on the Usb Serial Device\r
+\r
+  @retval EFI_SUCCESS                The baudrate was set succesfully\r
+  @retval EFI_INVALID_PARAMETER      An invalid baudrate was used\r
+  @retval EFI_DEVICE_ERROR           The device is not functioning correctly and\r
+                                     the baudrate was unable to be set\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetBaudRateInternal (\r
+  IN EFI_USB_IO_PROTOCOL  *UsbIo,\r
+  IN UINT64               BaudRate,\r
+  IN UINT64               LastBaudRate\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_USB_DEVICE_REQUEST  DevReq;\r
+  UINT32                  ReturnValue;\r
+  UINT8                   ConfigurationValue;\r
+  UINT16                  EncodedBaudRate;\r
+  EFI_TPL                 Tpl;\r
+\r
+  Tpl    = gBS->RaiseTPL(TPL_NOTIFY);\r
+\r
+  //\r
+  // set the value of DevReq.Value based on the value of BaudRate\r
+  // if 0 is selected as baud rate use the value of LastBaudRate\r
+  //\r
+  if (BaudRate == 0) {\r
+    Status = EncodeBaudRateForFtdi (LastBaudRate, &EncodedBaudRate);\r
+    if (EFI_ERROR (Status)) {\r
+      gBS->RestoreTPL (Tpl);\r
+      //\r
+      // EncodeBaudRateForFtdi returns EFI_INVALID_PARAMETER when not\r
+      // succesfull\r
+      //\r
+      return Status;\r
+    }\r
+    DevReq.Value = EncodedBaudRate;\r
+  } else {\r
+    Status = EncodeBaudRateForFtdi (BaudRate, &EncodedBaudRate);\r
+    if (EFI_ERROR (Status)) {\r
+      gBS->RestoreTPL (Tpl);\r
+      //\r
+      // EncodeBaudRateForFtdi returns EFI_INVALID_PARAMETER when not\r
+      // successfull\r
+      //\r
+      return Status;\r
+    }\r
+    DevReq.Value = EncodedBaudRate;\r
+  }\r
+\r
+  //\r
+  // set the remaining parameters of DevReq and perform the usb control transfer\r
+  // to set the device\r
+  //\r
+  DevReq.Request     = FTDI_COMMAND_SET_BAUDRATE;\r
+  DevReq.RequestType = USB_REQ_TYPE_VENDOR;\r
+  DevReq.Index       = FTDI_PORT_IDENTIFIER;\r
+  DevReq.Length      = 0; // indicates that there is no data phase in this request\r
+\r
+  Status = UsbIo->UsbControlTransfer (\r
+                    UsbIo,\r
+                    &DevReq,\r
+                    EfiUsbDataOut,\r
+                    WDR_SHORT_TIMEOUT,\r
+                    &ConfigurationValue,\r
+                    1,\r
+                    &ReturnValue\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    goto StatusError;\r
+  }\r
+  gBS->RestoreTPL (Tpl);\r
+  return Status;\r
+\r
+StatusError:\r
+  gBS->RestoreTPL (Tpl);\r
+  if ((Status != EFI_INVALID_PARAMETER) || (Status != EFI_DEVICE_ERROR)) {\r
+    return EFI_DEVICE_ERROR;\r
+  } else {\r
+    return Status;\r
+  }\r
+}\r
+\r
+/**\r
+  Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,\r
+  data bits, and stop bits on a serial device.\r
+\r
+  @param  UsbSerialDevice[in]  Pointer to the current instance of the USB Serial\r
+                               Device.\r
+  @param  BaudRate[in]         The requested baud rate. A BaudRate value of 0\r
+                               will use the device's default interface speed.\r
+  @param  ReveiveFifoDepth[in] The requested depth of the FIFO on the receive\r
+                               side of the serial interface. A ReceiveFifoDepth\r
+                               value of 0 will use the device's default FIFO\r
+                               depth.\r
+  @param  Timeout[in]          The requested time out for a single character in\r
+                               microseconds.This timeout applies to both the\r
+                               transmit and receive side of the interface.A\r
+                               Timeout value of 0 will use the device's default\r
+                               time out value.\r
+  @param  Parity[in]           The type of parity to use on this serial device.\r
+                               A Parity value of DefaultParity will use the\r
+                               device's default parity value.\r
+  @param  DataBits[in]         The number of data bits to use on the serial\r
+                               device. A DataBits value of 0 will use the\r
+                               device's default data bit setting.\r
+  @param  StopBits[in]         The number of stop bits to use on this serial\r
+                               device. A StopBits value of DefaultStopBits will\r
+                               use the device's default number of stop bits.\r
+\r
+  @retval EFI_SUCCESS          The attributes were set\r
+  @retval EFI_DEVICE_ERROR     The attributes were not able to be set\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetAttributesInternal (\r
+  IN USB_SER_DEV         *UsbSerialDevice,\r
+  IN UINT64              BaudRate,\r
+  IN UINT32              ReceiveFifoDepth,\r
+  IN UINT32              Timeout,\r
+  IN EFI_PARITY_TYPE     Parity,\r
+  IN UINT8               DataBits,\r
+  IN EFI_STOP_BITS_TYPE  StopBits\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_TPL                   Tpl;\r
+  UART_DEVICE_PATH          *Uart;\r
+  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath;\r
+\r
+  Status = EFI_UNSUPPORTED;\r
+  Tpl    = gBS->RaiseTPL(TPL_NOTIFY);\r
+  Uart   = NULL;\r
+\r
+  //\r
+  // check for invalid combinations of parameters\r
+  //\r
+  if (((DataBits >= 6) && (DataBits <= 8)) && (StopBits == OneFiveStopBits)) {\r
+    return  EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // set data bits, parity and stop bits\r
+  //\r
+  Status = SetDataInternal (\r
+             UsbSerialDevice->UsbIo,\r
+             DataBits,\r
+             Parity,\r
+             StopBits,\r
+             &(UsbSerialDevice->LastSettings)\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto StatusError;\r
+  }\r
+  //\r
+  // set baudrate\r
+  //\r
+  Status = SetBaudRateInternal (\r
+             UsbSerialDevice->UsbIo,\r
+             BaudRate,\r
+             UsbSerialDevice->LastSettings.BaudRate\r
+             );\r
+  if (EFI_ERROR (Status)){\r
+    goto StatusError;\r
+  }\r
+\r
+  //\r
+  // update the values of UsbSerialDevice->LastSettings and UsbSerialDevice->SerialIo.Mode\r
+  //\r
+  if (BaudRate == 0) {\r
+    UsbSerialDevice->LastSettings.BaudRate   = UsbSerialDevice->LastSettings.BaudRate;\r
+    UsbSerialDevice->SerialIo.Mode->BaudRate = UsbSerialDevice->LastSettings.BaudRate;\r
+  } else {\r
+    UsbSerialDevice->LastSettings.BaudRate   = BaudRate;\r
+    UsbSerialDevice->SerialIo.Mode->BaudRate = BaudRate;\r
+  }\r
+\r
+  UsbSerialDevice->LastSettings.Timeout          = FTDI_TIMEOUT;\r
+  UsbSerialDevice->LastSettings.ReceiveFifoDepth = FTDI_MAX_RECEIVE_FIFO_DEPTH;\r
+\r
+  if (Parity == DefaultParity) {\r
+    UsbSerialDevice->LastSettings.Parity   = UsbSerialDevice->LastSettings.Parity;\r
+    UsbSerialDevice->SerialIo.Mode->Parity = UsbSerialDevice->LastSettings.Parity;\r
+  } else {\r
+    UsbSerialDevice->LastSettings.Parity   = Parity;\r
+    UsbSerialDevice->SerialIo.Mode->Parity = Parity;\r
+  }\r
+  if (DataBits == 0) {\r
+    UsbSerialDevice->LastSettings.DataBits   = UsbSerialDevice->LastSettings.DataBits;\r
+    UsbSerialDevice->SerialIo.Mode->DataBits = UsbSerialDevice->LastSettings.DataBits;\r
+  } else {\r
+    UsbSerialDevice->LastSettings.DataBits   = DataBits;\r
+    UsbSerialDevice->SerialIo.Mode->DataBits = DataBits;\r
+  }\r
+  if (StopBits == DefaultStopBits) {\r
+    UsbSerialDevice->LastSettings.StopBits   = UsbSerialDevice->LastSettings.StopBits;\r
+    UsbSerialDevice->SerialIo.Mode->StopBits = UsbSerialDevice->LastSettings.StopBits;\r
+  } else {\r
+    UsbSerialDevice->LastSettings.StopBits   = StopBits;\r
+    UsbSerialDevice->SerialIo.Mode->StopBits = StopBits;\r
+  }\r
+\r
+  //\r
+  // See if the device path node has changed\r
+  //\r
+  if (UsbSerialDevice->UartDevicePath.BaudRate == BaudRate &&\r
+      UsbSerialDevice->UartDevicePath.DataBits == DataBits &&\r
+      UsbSerialDevice->UartDevicePath.StopBits == StopBits &&\r
+      UsbSerialDevice->UartDevicePath.Parity == Parity\r
+      ) {\r
+    gBS->RestoreTPL (Tpl);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Update the device path\r
+  //\r
+  UsbSerialDevice->UartDevicePath.BaudRate = BaudRate;\r
+  UsbSerialDevice->UartDevicePath.DataBits = DataBits;\r
+  UsbSerialDevice->UartDevicePath.StopBits = (UINT8) StopBits;\r
+  UsbSerialDevice->UartDevicePath.Parity   = (UINT8) Parity;\r
+\r
+  Status = EFI_SUCCESS;\r
+  if (UsbSerialDevice->ControllerHandle != NULL) {\r
+    RemainingDevicePath = UsbSerialDevice->DevicePath;\r
+    while (!IsDevicePathEnd (RemainingDevicePath)) {\r
+      Uart = (UART_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);\r
+      if (Uart->Header.Type == MESSAGING_DEVICE_PATH &&\r
+          Uart->Header.SubType == MSG_UART_DP &&\r
+          sizeof (UART_DEVICE_PATH) == DevicePathNodeLength ((EFI_DEVICE_PATH *) Uart)) {\r
+        Uart->BaudRate = BaudRate;\r
+        Uart->DataBits = DataBits;\r
+        Uart->StopBits = (UINT8)StopBits;\r
+        Uart->Parity   = (UINT8) Parity;\r
+        break;\r
+        }\r
+        RemainingDevicePath = NextDevicePathNode (RemainingDevicePath);\r
+    }\r
+  }\r
+\r
+  gBS->RestoreTPL (Tpl);\r
+  return Status;\r
+\r
+StatusError:\r
+  gBS->RestoreTPL (Tpl);\r
+  if ((Status != EFI_INVALID_PARAMETER) || (Status != EFI_DEVICE_ERROR)) {\r
+    return EFI_DEVICE_ERROR;\r
+  } else {\r
+    return Status;\r
+  }\r
+}\r
+\r
+/**\r
+  Internal function that performs a Usb Control Transfer to set the flow control\r
+  on the Usb Serial Device.\r
+\r
+  @param  UsbIo[in]                  Usb Io Protocol instance pointer\r
+  @param  FlowControlEnable[in]      Data on the Enable/Disable status of Flow\r
+                                     Control on the Usb Serial Device\r
+\r
+  @retval EFI_SUCCESS                The flow control was set on the Usb Serial\r
+                                     device\r
+  @retval EFI_INVALID_PARAMETER      An invalid flow control value was used\r
+  @retval EFI_EFI_UNSUPPORTED        The operation is not supported\r
+  @retval EFI_DEVICE_ERROR           The device is not functioning correctly\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetFlowControlInternal (\r
+  IN EFI_USB_IO_PROTOCOL  *UsbIo,\r
+  IN BOOLEAN              FlowControlEnable\r
+  )\r
+{\r
+  EFI_STATUS               Status;\r
+  EFI_USB_DEVICE_REQUEST   DevReq;\r
+  UINT32                   ReturnValue;\r
+  UINT8                    ConfigurationValue;\r
+\r
+  //\r
+  // set DevReq.Value based on the value of FlowControlEnable\r
+  //\r
+  if (!FlowControlEnable) {\r
+    DevReq.Value = NO_FLOW_CTRL;\r
+  }\r
+  if (FlowControlEnable) {\r
+    DevReq.Value = XON_XOFF_CTRL;\r
+  }\r
+  //\r
+  // set the remaining DevReq parameters and perform the usb control transfer to\r
+  // set the flow control on the device\r
+  //\r
+  DevReq.Request      = FTDI_COMMAND_SET_FLOW_CTRL;\r
+  DevReq.RequestType  = USB_REQ_TYPE_VENDOR;\r
+  DevReq.Index        = FTDI_PORT_IDENTIFIER;\r
+  DevReq.Length       = 0; // indicates that this transfer has no data phase\r
+  Status              = UsbIo->UsbControlTransfer (\r
+                                 UsbIo,\r
+                                 &DevReq,\r
+                                 EfiUsbDataOut,\r
+                                 WDR_TIMEOUT,\r
+                                 &ConfigurationValue,\r
+                                 1,\r
+                                 &ReturnValue\r
+                                 );\r
+  if (EFI_ERROR (Status)) {\r
+    goto StatusError;\r
+  }\r
+\r
+  return Status;\r
+\r
+StatusError:\r
+  if ((Status != EFI_INVALID_PARAMETER) ||\r
+      (Status != EFI_DEVICE_ERROR)      ||\r
+      (Status != EFI_UNSUPPORTED)          ) {\r
+    return EFI_DEVICE_ERROR;\r
+  } else {\r
+    return Status;\r
+  }\r
+}\r
+\r
+/**\r
+  Internal function that performs a Usb Control Transfer to set the Dtr value on\r
+  the Usb Serial Device.\r
+\r
+  @param  UsbIo[in]                  Usb Io Protocol instance pointer\r
+  @param  DtrEnable[in]              Data on the Enable/Disable status of the\r
+                                     Dtr for the Usb Serial Device\r
+\r
+  @retval EFI_SUCCESS                The Dtr value was set on the Usb Serial\r
+                                     Device\r
+  @retval EFI_INVALID_PARAMETER      An invalid Dtr value was used\r
+  @retval EFI_UNSUPPORTED            The operation is not supported\r
+  @retval EFI_DEVICE_ERROR           The device is not functioning correctly\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetDtrInternal (\r
+  IN EFI_USB_IO_PROTOCOL  *UsbIo,\r
+  IN BOOLEAN              DtrEnable\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_USB_DEVICE_REQUEST  DevReq;\r
+  UINT32                  ReturnValue;\r
+  UINT8                   ConfigurationValue;\r
+\r
+  //\r
+  // set the value of DevReq.Value based on the value of DtrEnable\r
+  //\r
+  if (!DtrEnable) {\r
+    DevReq.Value = SET_DTR_LOW;\r
+  }\r
+  if (DtrEnable) {\r
+    DevReq.Value = SET_DTR_HIGH;\r
+  }\r
+  //\r
+  // set the remaining attributes of DevReq and perform the usb control transfer\r
+  // to set the device\r
+  //\r
+  DevReq.Request      = FTDI_COMMAND_MODEM_CTRL;\r
+  DevReq.RequestType  = USB_REQ_TYPE_VENDOR;\r
+  DevReq.Index        = FTDI_PORT_IDENTIFIER;\r
+  DevReq.Length       = 0; // indicates that there is no data phase in this transfer\r
+\r
+  Status = UsbIo->UsbControlTransfer (\r
+                    UsbIo,\r
+                    &DevReq,\r
+                    EfiUsbDataOut,\r
+                    WDR_TIMEOUT,\r
+                    &ConfigurationValue,\r
+                    1,\r
+                    &ReturnValue\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    goto StatusError;\r
+  }\r
+  return Status;\r
+\r
+StatusError:\r
+  if ((Status != EFI_INVALID_PARAMETER) ||\r
+      (Status != EFI_DEVICE_ERROR)      ||\r
+      (Status != EFI_UNSUPPORTED)          ) {\r
+    return EFI_DEVICE_ERROR;\r
+  } else {\r
+    return Status;\r
+  }\r
+}\r
+\r
+/**\r
+  Internal function that performs a Usb Control Transfer to set the Dtr value on\r
+  the Usb Serial Device.\r
+  \r
+  @param  UsbIo[in]                  Usb Io Protocol instance pointer\r
+  @param  RtsEnable[in]              Data on the Enable/Disable status of the\r
+                                     Rts for the Usb Serial Device\r
+\r
+  @retval EFI_SUCCESS                The Rts value was set on the Usb Serial\r
+                                     Device\r
+  @retval EFI_INVALID_PARAMETER      An invalid Rts value was used\r
+  @retval EFI_UNSUPPORTED            The operation is not supported\r
+  @retval EFI_DEVICE_ERROR           The device is not functioning correctly\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetRtsInternal (\r
+  IN EFI_USB_IO_PROTOCOL  *UsbIo,\r
+  IN BOOLEAN              RtsEnable\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_USB_DEVICE_REQUEST  DevReq;\r
+  UINT32                  ReturnValue;\r
+  UINT8                   ConfigurationValue;\r
+\r
+  //\r
+  // set DevReq.Value based on the value of RtsEnable\r
+  //\r
+  if (!RtsEnable) {\r
+    DevReq.Value = SET_RTS_LOW;\r
+  }\r
+  if (RtsEnable) {\r
+    DevReq.Value = SET_RTS_HIGH;\r
+  }\r
+\r
+  //\r
+  // set the remaining parameters of DevReq and perform the usb control transfer\r
+  // to set the values on the device\r
+  //\r
+  DevReq.Request     = FTDI_COMMAND_MODEM_CTRL;\r
+  DevReq.RequestType = USB_REQ_TYPE_VENDOR;\r
+  DevReq.Index       = FTDI_PORT_IDENTIFIER;\r
+  DevReq.Length      = 0; // indicates that there is no data phase in this request\r
+\r
+  Status = UsbIo->UsbControlTransfer (\r
+                    UsbIo,\r
+                    &DevReq,\r
+                    EfiUsbDataOut,\r
+                    WDR_TIMEOUT,\r
+                    &ConfigurationValue,\r
+                    1,\r
+                    &ReturnValue\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    goto StatusError;\r
+  }\r
+\r
+  return Status;\r
+\r
+StatusError:\r
+  if ((Status != EFI_INVALID_PARAMETER) ||\r
+      (Status != EFI_DEVICE_ERROR)      ||\r
+      (Status != EFI_UNSUPPORTED)          ) {\r
+    return EFI_DEVICE_ERROR;\r
+  } else {\r
+    return Status;\r
+  }\r
+}\r
+\r
+/**\r
+  Internal function that checks for valid control values and sets the control\r
+  bits on the Usb Serial Device.\r
+\r
+  @param  UsbSerialDevice[in]        Handle to the Usb Serial Device whose\r
+                                     control bits are being set\r
+  @param  Control[in]                The control value passed to the function\r
+                                     that contains the values of the control\r
+                                     bits that are being set\r
+\r
+  @retval EFI_SUCCESS                The control bits were set on the Usb Serial\r
+                                     Device\r
+  @retval EFI_INVALID_PARAMETER      An invalid control value was encountered\r
+  @retval EFI_EFI_UNSUPPORTED        The operation is not supported\r
+  @retval EFI_DEVICE_ERROR           The device is not functioning correctly\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetControlBitsInternal (\r
+  IN USB_SER_DEV   *UsbSerialDevice,\r
+  IN CONTROL_BITS  *Control\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;\r
+  EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath;\r
+\r
+  //\r
+  // check for invalid control parameters hardware and software loopback enabled\r
+  // must always be set to FALSE\r
+  //\r
+  Control->HardwareLoopBack = FALSE;\r
+  Control->SoftwareLoopBack = FALSE;\r
+\r
+  //\r
+  // set hardware flow control\r
+  //\r
+  Status  = SetFlowControlInternal (\r
+              UsbSerialDevice->UsbIo,\r
+              Control->HardwareFlowControl\r
+              );\r
+  if (EFI_ERROR (Status)) {\r
+    goto StatusError;\r
+  }\r
+\r
+  //\r
+  // set Dtr state\r
+  //\r
+  Status = SetDtrInternal (UsbSerialDevice->UsbIo, Control->DtrState);\r
+  if (EFI_ERROR (Status)) {\r
+    goto StatusError;\r
+  }\r
+\r
+  //\r
+  // set Rts state\r
+  //\r
+  Status = SetRtsInternal (UsbSerialDevice->UsbIo, Control->RtsState);\r
+  if (EFI_ERROR (Status)){\r
+    goto StatusError;\r
+  }\r
+\r
+  //\r
+  // update the remaining control values for UsbSerialDevice->ControlValues\r
+  //\r
+  UsbSerialDevice->ControlValues.DtrState            = Control->DtrState;\r
+  UsbSerialDevice->ControlValues.RtsState            = Control->RtsState;\r
+  UsbSerialDevice->ControlValues.HardwareFlowControl = Control->HardwareFlowControl;\r
+  UsbSerialDevice->ControlValues.HardwareLoopBack    = FALSE;\r
+  UsbSerialDevice->ControlValues.SoftwareLoopBack    = FALSE;\r
+\r
+  Status = EFI_SUCCESS;\r
+  //\r
+  // Update the device path to have the correct flow control values\r
+  //\r
+  if (UsbSerialDevice->ControllerHandle != NULL) {\r
+    RemainingDevicePath = UsbSerialDevice->DevicePath;\r
+    while (!IsDevicePathEnd (RemainingDevicePath)) {\r
+      FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);\r
+      if (FlowControl->Header.Type == MESSAGING_DEVICE_PATH &&\r
+          FlowControl->Header.SubType == MSG_VENDOR_DP &&\r
+          sizeof (UART_FLOW_CONTROL_DEVICE_PATH) == DevicePathNodeLength ((EFI_DEVICE_PATH *) FlowControl)){\r
+        if (UsbSerialDevice->ControlValues.HardwareFlowControl == TRUE) {\r
+          FlowControl->FlowControlMap = UART_FLOW_CONTROL_HARDWARE;\r
+        } else if (UsbSerialDevice->ControlValues.HardwareFlowControl == FALSE) {\r
+          FlowControl->FlowControlMap = 0;\r
+        }\r
+        break;\r
+      }\r
+      RemainingDevicePath = NextDevicePathNode (RemainingDevicePath);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+\r
+StatusError:\r
+  if ((Status != EFI_INVALID_PARAMETER) ||\r
+      (Status != EFI_DEVICE_ERROR)      ||\r
+      (Status != EFI_UNSUPPORTED)          ) {\r
+    return EFI_DEVICE_ERROR;\r
+  } else {\r
+    return Status;\r
+  }\r
+}\r
+\r
+/**\r
+  Internal function that calculates the Control value used by GetControlBits()\r
+  based on the status and control values of the Usb Serial Device.\r
+\r
+  @param  UsbSerialDevice[in]        Handle to the Usb Serial Devie whose status\r
+                                     and control values are being used to set\r
+                                     Control\r
+  @param  Control[out]               On output the formated value of Control\r
+                                     that has been calculated based on the\r
+                                     control and status values of the Usb Serial\r
+                                     Device\r
+\r
+  @retval EFI_SUCCESS                The value of Control was successfully\r
+                                     calculated\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetControlBitsInternal (\r
+  IN USB_SER_DEV  *UsbSerialDevice,\r
+  OUT UINT32      *Control\r
+  )\r
+{\r
+  *Control = 0;\r
+\r
+  //\r
+  // Check the values of UsbSerialDevice->Status Values and modify control\r
+  // accordingly these values correspond to the modem status register\r
+  //\r
+  if (UsbSerialDevice->StatusValues.CtsState) {\r
+    *Control |= EFI_SERIAL_CLEAR_TO_SEND;\r
+  }\r
+  if (UsbSerialDevice->StatusValues.DsrState) {\r
+    *Control |= EFI_SERIAL_DATA_SET_READY;\r
+  }\r
+  if (UsbSerialDevice->StatusValues.RiState) {\r
+    *Control |= EFI_SERIAL_RING_INDICATE;\r
+  }\r
+  if (UsbSerialDevice->StatusValues.SdState) {\r
+    *Control |= EFI_SERIAL_CARRIER_DETECT;\r
+  }\r
+\r
+  //\r
+  // check the values of UsbSerialDevice->ControlValues and modify control\r
+  // accordingly these values correspond to the values of the Modem Control\r
+  // Register\r
+  //\r
+  if (UsbSerialDevice->ControlValues.DtrState) {\r
+    *Control |= EFI_SERIAL_DATA_TERMINAL_READY;\r
+  }\r
+  if (UsbSerialDevice->ControlValues.RtsState) {\r
+    *Control |= EFI_SERIAL_REQUEST_TO_SEND;\r
+  }\r
+  if (UsbSerialDevice->ControlValues.HardwareLoopBack) {\r
+    *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;\r
+  }\r
+  if (UsbSerialDevice->ControlValues.HardwareFlowControl) {\r
+    *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
+  }\r
+  //\r
+  // check if the buffer is empty since only one is being used if it is empty\r
+  // set both the receive and transmit buffers to empty\r
+  //\r
+  if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {\r
+    *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;\r
+    *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;\r
+  }\r
+  //\r
+  // check for software loopback enable in UsbSerialDevice->ControlValues\r
+  //\r
+  if (UsbSerialDevice->ControlValues.SoftwareLoopBack) {\r
+    *Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Resets the USB Serial Device\r
+\r
+  This function is the internal method for reseting the device and is called by\r
+  SerialReset()\r
+\r
+  @param  UsbSerialDevice[in]  A pointer to the USB Serial device\r
+\r
+  @retval EFI_SUCCESS          The device was reset\r
+  @retval EFI_DEVICE_ERROR     The device could not be reset\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ResetInternal (\r
+  IN USB_SER_DEV  *UsbSerialDevice\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_USB_DEVICE_REQUEST  DevReq;\r
+  UINT8                   ConfigurationValue;\r
+  UINT32                  ReturnValue;\r
+\r
+  DevReq.Request     = FTDI_COMMAND_RESET_PORT;\r
+  DevReq.RequestType = USB_REQ_TYPE_VENDOR;\r
+  DevReq.Value       = RESET_PORT_PURGE_RX;\r
+  DevReq.Index       = FTDI_PORT_IDENTIFIER;\r
+  DevReq.Length      = 0; //indicates that there is not data phase in this request\r
+\r
+  Status = UsbSerialDevice->UsbIo->UsbControlTransfer (\r
+                                     UsbSerialDevice->UsbIo,\r
+                                     &DevReq,\r
+                                     EfiUsbDataIn,\r
+                                     WDR_TIMEOUT,\r
+                                     &ConfigurationValue,\r
+                                     1,\r
+                                     &ReturnValue\r
+                                     );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  DevReq.Request     = FTDI_COMMAND_RESET_PORT;\r
+  DevReq.RequestType = USB_REQ_TYPE_VENDOR;\r
+  DevReq.Value       = RESET_PORT_PURGE_TX;\r
+  DevReq.Index       = FTDI_PORT_IDENTIFIER;\r
+  DevReq.Length      = 0; //indicates that there is no data phase in this request\r
+\r
+  Status = UsbSerialDevice->UsbIo->UsbControlTransfer (\r
+                                     UsbSerialDevice->UsbIo,\r
+                                     &DevReq,\r
+                                     EfiUsbDataIn,\r
+                                     WDR_TIMEOUT,\r
+                                     &ConfigurationValue,\r
+                                     1,\r
+                                     &ReturnValue\r
+                                     );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Entrypoint of USB Serial Driver.\r
+\r
+  This function is the entrypoint of USB Serial Driver. It installs\r
+  Driver Binding Protocols together with Component Name Protocols.\r
+\r
+  @param  ImageHandle[in]       The firmware allocated handle for the EFI image.\r
+  @param  SystemTable[in]       A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS           The entry point is executed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FtdiUsbSerialEntryPoint (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
+             ImageHandle,\r
+             SystemTable,\r
+             &gUsbSerialDriverBinding,\r
+             ImageHandle,\r
+             &gUsbSerialComponentName,\r
+             &gUsbSerialComponentName2\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Unload function for the Usb Serial Driver.\r
+\r
+  @param  ImageHandle[in]    The allocated handle for the EFI image\r
+\r
+  @retval EFI_SUCCESS        The driver was unloaded successfully\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FtdiUsbSerialUnload (\r
+  IN EFI_HANDLE  ImageHandle\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_HANDLE  *HandleBuffer;\r
+  UINTN       HandleCount;\r
+  UINTN       Index;\r
+\r
+  //\r
+  // Retrieve all handles in the handle database\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  AllHandles,\r
+                  NULL,\r
+                  NULL,\r
+                  &HandleCount,\r
+                  &HandleBuffer\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Disconnect the driver from the handles in the handle database\r
+  //\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    Status = gBS->DisconnectController (\r
+                    HandleBuffer[Index],\r
+                    gImageHandle,\r
+                    NULL\r
+                    );\r
+  }\r
+\r
+  //\r
+  // Free the handle array\r
+  //\r
+  FreePool (HandleBuffer);\r
+\r
+  //\r
+  // Uninstall protocols installed by the driver in its entrypoint\r
+  //\r
+  Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                  ImageHandle,\r
+                  &gEfiDriverBindingProtocolGuid,\r
+                  &gUsbSerialDriverBinding,\r
+                  &gEfiComponentNameProtocolGuid,\r
+                  &gUsbSerialComponentName,\r
+                  &gEfiComponentName2ProtocolGuid,\r
+                  &gUsbSerialComponentName2,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Check whether USB Serial driver supports this device.\r
+\r
+  @param  This[in]                   The USB Serial driver binding protocol.\r
+  @param  Controller[in]             The controller handle to check.\r
+  @param  RemainingDevicePath[in]    The remaining device path.\r
+\r
+  @retval EFI_SUCCESS                The driver supports this controller.\r
+  @retval other                      This device isn't supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbSerialDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS           Status;\r
+  EFI_USB_IO_PROTOCOL  *UsbIo;\r
+  UART_DEVICE_PATH     *UartNode;\r
+  UART_FLOW_CONTROL_DEVICE_PATH        *FlowControlNode;\r
+  UINTN                                Index;\r
+  UINTN                                EntryCount;\r
+  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY  *OpenInfoBuffer;\r
+  BOOLEAN                              HasFlowControl;\r
+  EFI_DEVICE_PATH_PROTOCOL             *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL             *ParentDevicePath;\r
+\r
+  if (RemainingDevicePath != NULL) {\r
+    if (!IsDevicePathEnd (RemainingDevicePath)) {\r
+      Status = EFI_UNSUPPORTED;\r
+      UartNode = (UART_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);\r
+      if (UartNode->Header.Type != MESSAGING_DEVICE_PATH ||\r
+          UartNode->Header.SubType != MSG_UART_DP ||\r
+          sizeof (UART_DEVICE_PATH) != DevicePathNodeLength ((EFI_DEVICE_PATH *) UartNode)) {\r
+        goto Error;\r
+      }\r
+      FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (UartNode);\r
+      if ((ReadUnaligned32 (&FlowControlNode->FlowControlMap) & ~UART_FLOW_CONTROL_HARDWARE) != 0) {\r
+        goto Error;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Check if USB I/O Protocol is attached on the controller handle.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiUsbIoProtocolGuid,\r
+                  (VOID **) &UsbIo,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {\r
+      return EFI_SUCCESS;\r
+    }\r
+    Status = gBS->OpenProtocolInformation (\r
+                    Controller,\r
+                    &gEfiUsbIoProtocolGuid,\r
+                    &OpenInfoBuffer,\r
+                    &EntryCount\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    for (Index = 0; Index < EntryCount; Index++) {\r
+      if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
+        Status = gBS->OpenProtocol (\r
+                        OpenInfoBuffer[Index].ControllerHandle,\r
+                        &gEfiDevicePathProtocolGuid,\r
+                        (VOID **) &DevicePath,\r
+                        This->DriverBindingHandle,\r
+                        Controller,\r
+                        EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                        );\r
+        if (!EFI_ERROR (Status)) {\r
+          HasFlowControl = ContainsFlowControl (RemainingDevicePath);\r
+          if (HasFlowControl ^ ContainsFlowControl (DevicePath)) {\r
+            Status = EFI_UNSUPPORTED;\r
+          }\r
+        }\r
+        break;\r
+      }\r
+    }\r
+    FreePool (OpenInfoBuffer);\r
+    return Status;\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiUsbIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &ParentDevicePath,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Use the USB I/O Protocol interface to check whether Controller is\r
+  // a USB Serial device that can be managed by this driver.\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  if (!IsUsbSerial (UsbIo)) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto Error;\r
+  }\r
+\r
+Error:\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiDevicePathProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Starts the USB Serial device with this driver.\r
+\r
+  This function produces initializes the USB Serial device and\r
+  produces the Serial IO Protocol.\r
+\r
+  @param  This[in]                   The USB Serial driver binding instance.\r
+  @param  Controller[in]             Handle of device to bind driver to.\r
+  @param  RemainingDevicePath[in]    Optional parameter use to pick a specific\r
+                                     child device to start.\r
+\r
+  @retval EFI_SUCCESS                The controller is controlled by the usb USB\r
+                                     Serial driver.\r
+  @retval EFI_UNSUPPORTED            No interrupt endpoint can be found.\r
+  @retval Other                      This controller cannot be started.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbSerialDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  EFI_USB_IO_PROTOCOL                 *UsbIo;\r
+  USB_SER_DEV                         *UsbSerialDevice;\r
+  UINT8                               EndpointNumber;\r
+  EFI_USB_ENDPOINT_DESCRIPTOR         EndpointDescriptor;\r
+  UINT8                               Index;\r
+  BOOLEAN                             FoundIn;\r
+  BOOLEAN                             FoundOut;\r
+  EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;\r
+  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
+  UINTN                               EntryCount;\r
+  EFI_SERIAL_IO_PROTOCOL              *SerialIo;\r
+  UART_DEVICE_PATH                    *Uart;\r
+  UART_FLOW_CONTROL_DEVICE_PATH       *FlowControl;\r
+  UINT32                              FlowControlMap;\r
+  UINT32                              Control;\r
+  EFI_DEVICE_PATH_PROTOCOL            *TempDevicePath;\r
+\r
+  UsbSerialDevice = AllocateZeroPool (sizeof (USB_SER_DEV));\r
+  ASSERT (UsbSerialDevice != NULL);\r
+\r
+  //\r
+  // Get the Parent Device path\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &ParentDevicePath,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+    goto ErrorExit1;\r
+  }\r
+\r
+  //\r
+  // Open USB I/O Protocol\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiUsbIoProtocolGuid,\r
+                  (VOID **) &UsbIo,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+    goto ErrorExit1;\r
+  }\r
+\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {\r
+      FreePool (UsbSerialDevice);\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    //\r
+    // Check to see if a child handle exists\r
+    //\r
+    Status = gBS->OpenProtocolInformation (\r
+                    Controller,\r
+                    &gEfiSerialIoProtocolGuid,\r
+                    &OpenInfoBuffer,\r
+                    &EntryCount\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ErrorExit1;\r
+    }\r
+\r
+    Status = EFI_ALREADY_STARTED;\r
+    for (Index = 0; Index < EntryCount; Index++) {\r
+      if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
+        Status = gBS->OpenProtocol (\r
+                        OpenInfoBuffer[Index].ControllerHandle,\r
+                        &gEfiSerialIoProtocolGuid,\r
+                        (VOID **) &SerialIo,\r
+                        This->DriverBindingHandle,\r
+                        Controller,\r
+                        EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                        );\r
+        if (EFI_ERROR (Status)) {\r
+        }\r
+        if (!EFI_ERROR (Status)) {\r
+          Uart = (UART_DEVICE_PATH *) RemainingDevicePath;\r
+          Status = SerialIo->SetAttributes (\r
+                               SerialIo,\r
+                               Uart->BaudRate,\r
+                               SerialIo->Mode->ReceiveFifoDepth,\r
+                               SerialIo->Mode->Timeout,\r
+                               (EFI_PARITY_TYPE) Uart->Parity,\r
+                               Uart->DataBits,\r
+                               (EFI_STOP_BITS_TYPE) Uart->StopBits\r
+                               );\r
+          FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart);\r
+          if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) {\r
+            Status = SerialIo->GetControl (\r
+                                 SerialIo,\r
+                                 &Control\r
+                                 );\r
+            if (!EFI_ERROR (Status)) {\r
+              if (ReadUnaligned32 (&FlowControl->FlowControlMap) == UART_FLOW_CONTROL_HARDWARE) {\r
+                Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
+              } else {\r
+                Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
+              }\r
+              //\r
+              // Clear bits that are not allowed to be passed to SetControl\r
+              //\r
+              Control &= (EFI_SERIAL_REQUEST_TO_SEND | \r
+                          EFI_SERIAL_DATA_TERMINAL_READY |\r
+                          EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE |\r
+                          EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |\r
+                          EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE);\r
+              Status = SerialIo->SetControl (SerialIo, Control);\r
+            }\r
+          }\r
+        }\r
+        break;\r
+      }\r
+    }\r
+    FreePool (OpenInfoBuffer);\r
+    return Status;\r
+  }\r
+\r
+  if (RemainingDevicePath != NULL) {\r
+    if (IsDevicePathEnd (RemainingDevicePath)) {\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  UsbSerialDevice->UsbIo = UsbIo;\r
+\r
+  //\r
+  // Get interface & endpoint descriptor\r
+  //\r
+  UsbIo->UsbGetInterfaceDescriptor (\r
+           UsbIo,\r
+           &UsbSerialDevice->InterfaceDescriptor\r
+           );\r
+\r
+  EndpointNumber = UsbSerialDevice->InterfaceDescriptor.NumEndpoints;\r
+\r
+  //\r
+  // Traverse endpoints to find the IN and OUT endpoints that will send and\r
+  // receive data.\r
+  //\r
+  FoundIn = FALSE;\r
+  FoundOut = FALSE;\r
+  for (Index = 0; Index < EndpointNumber; Index++) {\r
+\r
+    Status = UsbIo->UsbGetEndpointDescriptor (\r
+                      UsbIo,\r
+                      Index,\r
+                      &EndpointDescriptor\r
+                      );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    if (EndpointDescriptor.EndpointAddress == FTDI_ENDPOINT_ADDRESS_OUT) {\r
+      //\r
+      // Set the Out endpoint device\r
+      //\r
+      CopyMem (\r
+        &UsbSerialDevice->OutEndpointDescriptor,\r
+        &EndpointDescriptor,\r
+        sizeof(EndpointDescriptor)\r
+        );\r
+      FoundOut = TRUE;\r
+    }\r
+\r
+    if (EndpointDescriptor.EndpointAddress == FTDI_ENDPOINT_ADDRESS_IN) {\r
+      //\r
+      // Set the In endpoint device\r
+      //\r
+      CopyMem (\r
+        &UsbSerialDevice->InEndpointDescriptor,\r
+        &EndpointDescriptor,\r
+        sizeof(EndpointDescriptor)\r
+        );\r
+      FoundIn = TRUE;\r
+    }\r
+  }\r
+\r
+  if (!FoundIn || !FoundOut) {\r
+    //\r
+    // No interrupt endpoint found, then return unsupported.\r
+    //\r
+    Status = EFI_UNSUPPORTED;\r
+    goto ErrorExit;\r
+  }\r
+  //\r
+  // set the initial values of UsbSerialDevice->LastSettings to the default\r
+  // values\r
+  //\r
+  UsbSerialDevice->LastSettings.BaudRate         = 115200;\r
+  UsbSerialDevice->LastSettings.DataBits         = 8;\r
+  UsbSerialDevice->LastSettings.Parity           = NoParity;\r
+  UsbSerialDevice->LastSettings.ReceiveFifoDepth = FTDI_MAX_RECEIVE_FIFO_DEPTH;\r
+  UsbSerialDevice->LastSettings.StopBits         = OneStopBit;\r
+  UsbSerialDevice->LastSettings.Timeout          = FTDI_TIMEOUT;\r
+\r
+  //\r
+  // set the initial values of UsbSerialDevice->ControlValues\r
+  //\r
+  UsbSerialDevice->ControlValues.DtrState            = FALSE;\r
+  UsbSerialDevice->ControlValues.RtsState            = FALSE;\r
+  UsbSerialDevice->ControlValues.HardwareFlowControl = FALSE;\r
+  UsbSerialDevice->ControlValues.HardwareLoopBack    = FALSE;\r
+  UsbSerialDevice->ControlValues.SoftwareLoopBack    = FALSE;\r
+\r
+  //\r
+  // set the values of UsbSerialDevice->UartDevicePath\r
+  //\r
+  UsbSerialDevice->UartDevicePath.Header.Type    = MESSAGING_DEVICE_PATH;\r
+  UsbSerialDevice->UartDevicePath.Header.SubType = MSG_UART_DP;\r
+  UsbSerialDevice->UartDevicePath.Header.Length[0] = (UINT8) (sizeof (UART_DEVICE_PATH));\r
+  UsbSerialDevice->UartDevicePath.Header.Length[1] = (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8);\r
+\r
+  //\r
+  // set the values of UsbSerialDevice->FlowControlDevicePath\r
+  UsbSerialDevice->FlowControlDevicePath.Header.Type = MESSAGING_DEVICE_PATH;\r
+  UsbSerialDevice->FlowControlDevicePath.Header.SubType = MSG_VENDOR_DP;\r
+  UsbSerialDevice->FlowControlDevicePath.Header.Length[0] = (UINT8) (sizeof (UART_FLOW_CONTROL_DEVICE_PATH));\r
+  UsbSerialDevice->FlowControlDevicePath.Header.Length[1] = (UINT8) ((sizeof (UART_FLOW_CONTROL_DEVICE_PATH)) >> 8);\r
+  UsbSerialDevice->FlowControlDevicePath.FlowControlMap = 0;\r
+\r
+  Status = SetAttributesInternal (\r
+             UsbSerialDevice, \r
+             UsbSerialDevice->LastSettings.BaudRate,\r
+             UsbSerialDevice->LastSettings.ReceiveFifoDepth, \r
+             UsbSerialDevice->LastSettings.Timeout,\r
+             UsbSerialDevice->LastSettings.Parity, \r
+             UsbSerialDevice->LastSettings.DataBits,\r
+             UsbSerialDevice->LastSettings.StopBits\r
+             );\r
+\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = SetControlBitsInternal (\r
+             UsbSerialDevice,\r
+             &(UsbSerialDevice->ControlValues)\r
+             );\r
+\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Publish Serial GUID and protocol\r
+  //\r
+\r
+  UsbSerialDevice->Signature              = USB_SER_DEV_SIGNATURE;\r
+  UsbSerialDevice->SerialIo.Reset         = SerialReset;\r
+  UsbSerialDevice->SerialIo.SetControl    = SetControlBits;\r
+  UsbSerialDevice->SerialIo.SetAttributes = SetAttributes;\r
+  UsbSerialDevice->SerialIo.GetControl    = GetControlBits;\r
+  UsbSerialDevice->SerialIo.Read          = ReadSerialIo;\r
+  UsbSerialDevice->SerialIo.Write         = WriteSerialIo;\r
+\r
+  //\r
+  // Set the static Serial IO modes that will display when running\r
+  // "sermode" within the UEFI shell.\r
+  //\r
+\r
+  UsbSerialDevice->SerialIo.Mode->Timeout  = 0;\r
+  UsbSerialDevice->SerialIo.Mode->BaudRate = 115200;\r
+  UsbSerialDevice->SerialIo.Mode->DataBits = 8;\r
+  UsbSerialDevice->SerialIo.Mode->Parity   = 1;\r
+  UsbSerialDevice->SerialIo.Mode->StopBits = 1;\r
+\r
+  UsbSerialDevice->ParentDevicePath = ParentDevicePath;\r
+  UsbSerialDevice->ControllerHandle = NULL;\r
+  FlowControl                       = NULL;\r
+  FlowControlMap                    = 0;\r
+\r
+  //\r
+  // Allocate space for the receive buffer\r
+  //\r
+  UsbSerialDevice->DataBuffer = AllocateZeroPool (SW_FIFO_DEPTH);\r
+\r
+  //\r
+  // Initialize data buffer pointers.\r
+  // Head==Tail = true means buffer is empty.\r
+  //\r
+  UsbSerialDevice->DataBufferHead = 0;\r
+  UsbSerialDevice->DataBufferTail = 0;\r
+\r
+  UsbSerialDevice->ControllerNameTable = NULL;\r
+  AddUnicodeString2 (\r
+    "eng",\r
+    gUsbSerialComponentName.SupportedLanguages,\r
+    &UsbSerialDevice->ControllerNameTable,\r
+    L"FTDI USB Serial Adapter",\r
+    TRUE\r
+    );\r
+  AddUnicodeString2 (\r
+    "en",\r
+    gUsbSerialComponentName2.SupportedLanguages,\r
+    &UsbSerialDevice->ControllerNameTable,\r
+    L"FTDI USB Serial Adapter",\r
+    FALSE\r
+    );\r
+\r
+  Status = SetInitialStatus (UsbSerialDevice);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Create a polling loop to check for input\r
+  //\r
+\r
+  gBS->CreateEvent (\r
+         EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+         TPL_CALLBACK,\r
+         UsbSerialDriverCheckInput,\r
+         UsbSerialDevice,\r
+         &(UsbSerialDevice->PollingLoop)\r
+         );\r
+  //\r
+  // add code to set trigger time based on baud rate\r
+  // setting to 0.5s for now\r
+  //\r
+  gBS->SetTimer (\r
+         UsbSerialDevice->PollingLoop,\r
+         TimerPeriodic,\r
+         EFI_TIMER_PERIOD_MILLISECONDS (500)\r
+         );\r
+\r
+  //\r
+  // Check if the remaining device path is null. If it is not null change the settings\r
+  // of the device to match those on the device path\r
+  //\r
+  if (RemainingDevicePath != NULL) {\r
+    CopyMem (\r
+      &UsbSerialDevice->UartDevicePath,\r
+      RemainingDevicePath,\r
+      sizeof (UART_DEVICE_PATH)\r
+      );\r
+    FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);\r
+    if (IsUartFlowControlNode (FlowControl)) {\r
+      UsbSerialDevice->FlowControlDevicePath.FlowControlMap = ReadUnaligned32 (&FlowControl->FlowControlMap);\r
+    } else {\r
+      FlowControl = NULL;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Build the device path by appending the UART node to the parent device path\r
+  //\r
+  UsbSerialDevice->DevicePath = AppendDevicePathNode (\r
+                                  ParentDevicePath,\r
+                                  (EFI_DEVICE_PATH_PROTOCOL *) &UsbSerialDevice->UartDevicePath\r
+                                  );\r
+  //\r
+  // Continue building the device path by appending the flow control node\r
+  //\r
+  TempDevicePath = UsbSerialDevice->DevicePath;\r
+  UsbSerialDevice->DevicePath = AppendDevicePathNode (\r
+                                  TempDevicePath,\r
+                                  (EFI_DEVICE_PATH_PROTOCOL *) &UsbSerialDevice->FlowControlDevicePath\r
+                                  );\r
+  FreePool (TempDevicePath);\r
+\r
+  if (UsbSerialDevice->DevicePath == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ErrorExit;\r
+  }\r
+\r
+  //\r
+  // Install protocol interfaces for the device\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &UsbSerialDevice->ControllerHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  UsbSerialDevice->DevicePath,\r
+                  &gEfiSerialIoProtocolGuid,\r
+                  &UsbSerialDevice->SerialIo,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)){\r
+    goto ErrorExit;\r
+  }\r
+\r
+  //\r
+  // Open for child device\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                 Controller,\r
+                 &gEfiUsbIoProtocolGuid,\r
+                 (VOID **) &UsbIo,\r
+                 This->DriverBindingHandle,\r
+                 UsbSerialDevice->ControllerHandle,\r
+                 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                 );\r
+\r
+  UsbSerialDevice->Shutdown = FALSE;\r
+\r
+  return EFI_SUCCESS;\r
+\r
+ErrorExit:\r
+  //\r
+  // Error handler\r
+  //\r
+\r
+  Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                  Controller,\r
+                  &gEfiSerialIoProtocolGuid,\r
+                  &UsbSerialDevice->SerialIo,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ErrorExit1;\r
+  }\r
+\r
+  FreePool (UsbSerialDevice->DataBuffer);\r
+  FreePool (UsbSerialDevice);\r
+\r
+  UsbSerialDevice = NULL;\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiUsbIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+\r
+ErrorExit1:\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Stop the USB Serial device handled by this driver.\r
+\r
+  @param  This[in]                   The USB Serial driver binding protocol.\r
+  @param  Controller[in]             The controller to release.\r
+  @param  NumberOfChildren[in]       The number of handles in ChildHandleBuffer.\r
+  @param  ChildHandleBuffer[in]      The array of child handle.\r
+\r
+  @retval EFI_SUCCESS                The device was stopped.\r
+  @retval EFI_UNSUPPORTED            Serial IO Protocol is not installed on\r
+                                     Controller.\r
+  @retval EFI_DEVICE_ERROR           The device could not be stopped due to a\r
+                                     device error.\r
+  @retval Others                     Fail to uninstall protocols attached on the\r
+                                     device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbSerialDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   Controller,\r
+  IN  UINTN                        NumberOfChildren,\r
+  IN  EFI_HANDLE                   *ChildHandleBuffer\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_SERIAL_IO_PROTOCOL    *SerialIo;\r
+  EFI_USB_IO_PROTOCOL       *UsbIo;\r
+  USB_SER_DEV               *UsbSerialDevice;\r
+  UINTN                     Index;\r
+  BOOLEAN                   AllChildrenStopped;\r
+\r
+  Status = EFI_SUCCESS;\r
+  UsbSerialDevice = NULL;\r
+\r
+  if (NumberOfChildren == 0) {\r
+    //\r
+    // Close the driver\r
+    //\r
+    Status = gBS->CloseProtocol (\r
+                    Controller,\r
+                    &gEfiUsbIoProtocolGuid,\r
+                    This->DriverBindingHandle,\r
+                    Controller\r
+                    );\r
+    Status = gBS->CloseProtocol (\r
+                    Controller,\r
+                    &gEfiDevicePathProtocolGuid,\r
+                    This->DriverBindingHandle,\r
+                    Controller\r
+                    );\r
+    return Status;\r
+  }\r
+\r
+  AllChildrenStopped = TRUE;\r
+\r
+  for (Index = 0; Index < NumberOfChildren ;Index++) {\r
+    Status = gBS->OpenProtocol (\r
+                    ChildHandleBuffer[Index],\r
+                    &gEfiSerialIoProtocolGuid,\r
+                    (VOID **) &SerialIo,\r
+                    This->DriverBindingHandle,\r
+                    Controller,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
+    if (Status == EFI_SUCCESS) {//!EFI_ERROR (Status)) {\r
+      UsbSerialDevice = USB_SER_DEV_FROM_THIS (SerialIo);\r
+      Status = gBS->CloseProtocol (\r
+                      Controller,\r
+                      &gEfiUsbIoProtocolGuid,\r
+                      This->DriverBindingHandle,\r
+                      ChildHandleBuffer[Index]\r
+                      );\r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                      ChildHandleBuffer[Index],\r
+                      &gEfiDevicePathProtocolGuid,\r
+                      UsbSerialDevice->DevicePath,\r
+                      &gEfiSerialIoProtocolGuid,\r
+                      &UsbSerialDevice->SerialIo,\r
+                      NULL\r
+                      );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        gBS->OpenProtocol (\r
+               Controller,\r
+               &gEfiUsbIoProtocolGuid,\r
+               (VOID **) &UsbIo,\r
+               This->DriverBindingHandle,\r
+               ChildHandleBuffer[Index],\r
+               EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+               );\r
+      } else {\r
+        if (UsbSerialDevice->DevicePath != NULL) {\r
+          gBS->FreePool (UsbSerialDevice->DevicePath);\r
+        }\r
+        gBS->SetTimer (\r
+               UsbSerialDevice->PollingLoop,\r
+               TimerCancel,\r
+               0\r
+               );\r
+        gBS->CloseEvent (UsbSerialDevice->PollingLoop);\r
+        UsbSerialDevice->Shutdown = TRUE;\r
+        FreeUnicodeStringTable (UsbSerialDevice->ControllerNameTable);\r
+        FreePool (UsbSerialDevice->DataBuffer);\r
+        FreePool (UsbSerialDevice);\r
+      }\r
+    }\r
+    if (EFI_ERROR (Status)) {\r
+      AllChildrenStopped = FALSE;\r
+    }\r
+  }\r
+\r
+  if (!AllChildrenStopped) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// Serial IO Member Functions\r
+//\r
+\r
+/**\r
+  Reset the serial device.\r
+\r
+  @param  This[in]              Protocol instance pointer.\r
+\r
+  @retval EFI_SUCCESS           The device was reset.\r
+  @retval EFI_DEVICE_ERROR      The serial device could not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SerialReset (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  USB_SER_DEV  *UsbSerialDevice;\r
+\r
+  UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);\r
+  Status          = ResetInternal (UsbSerialDevice);\r
+  if (EFI_ERROR (Status)){\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Set the control bits on a serial device.\r
+\r
+  @param  This[in]             Protocol instance pointer.\r
+  @param  Control[in]          Set the bits of Control that are settable.\r
+\r
+  @retval EFI_SUCCESS          The new control bits were set on the serial device.\r
+  @retval EFI_UNSUPPORTED      The serial device does not support this operation.\r
+  @retval EFI_DEVICE_ERROR     The serial device is not functioning correctly.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetControlBits (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This,\r
+  IN UINT32                  Control\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  USB_SER_DEV   *UsbSerialDevice;\r
+  CONTROL_BITS  ControlBits;\r
+  \r
+  UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);\r
+  \r
+  //\r
+  // check for invalid control parameters \r
+  //\r
+  if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND          |\r
+                    EFI_SERIAL_DATA_TERMINAL_READY      |\r
+                    EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE |\r
+                    EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |\r
+                    EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0 ) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // check the control parameters and set the correct setting for\r
+  // the paramerts of ControlBits\r
+  // both loopback enables are always set to FALSE\r
+  //\r
+  ControlBits.HardwareLoopBack = FALSE;\r
+  ControlBits.SoftwareLoopBack = FALSE;\r
+  //\r
+  // check for hardware flow control\r
+  //\r
+  if ((Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {\r
+    ControlBits.HardwareFlowControl = TRUE;\r
+  } else {\r
+    ControlBits.HardwareFlowControl = FALSE;\r
+  }\r
+  //\r
+  // check for DTR enabled\r
+  //\r
+  if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) {\r
+    ControlBits.DtrState = TRUE;\r
+  } else {\r
+    ControlBits.DtrState = FALSE;\r
+  }\r
+  //\r
+  // check for RTS enabled\r
+  //\r
+  if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) {\r
+    ControlBits.RtsState = TRUE;\r
+  } else {\r
+    ControlBits.RtsState = FALSE;\r
+  }\r
+\r
+  //\r
+  // set the control values with a call to SetControlBitsInternal()\r
+  //\r
+  Status = SetControlBitsInternal (UsbSerialDevice, &ControlBits);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  calls SetAttributesInternal() to set the baud rate, receive FIFO depth,\r
+  transmit/receive time out, parity, data buts, and stop bits on a serial\r
+  device.\r
+\r
+  @param  This[in]             Protocol instance pointer.\r
+  @param  BaudRate[in]         The requested baud rate. A BaudRate value of 0\r
+                               will use the device's default interface speed.\r
+  @param  ReveiveFifoDepth[in] The requested depth of the FIFO on the receive\r
+                               side of the serial interface. A ReceiveFifoDepth\r
+                               value of 0 will use the device's default FIFO\r
+                               depth.\r
+  @param  Timeout[in]          The requested time out for a single character in\r
+                               microseconds.This timeout applies to both the\r
+                               transmit and receive side of the interface. A\r
+                               Timeout value of 0 will use the device's default\r
+                               time out value.\r
+  @param  Parity[in]           The type of parity to use on this serial device.\r
+                               A Parity value of DefaultParity will use the\r
+                               device's default parity value.\r
+  @param  DataBits[in]         The number of data bits to use on the serial\r
+                               device. A DataBit vaule of 0 will use the\r
+                               device's default data bit setting.\r
+  @param  StopBits[in]         The number of stop bits to use on this serial\r
+                               device. A StopBits value of DefaultStopBits will\r
+                               use the device's default number of stop bits.\r
+\r
+  @retval EFI_SUCCESS          The attributes were set\r
+  @retval EFI_DEVICE_ERROR     The attributes were not able to be\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetAttributes (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This,\r
+  IN UINT64                  BaudRate,\r
+  IN UINT32                  ReceiveFifoDepth,\r
+  IN UINT32                  Timeout,\r
+  IN EFI_PARITY_TYPE         Parity,\r
+  IN UINT8                   DataBits,\r
+  IN EFI_STOP_BITS_TYPE      StopBits\r
+  )\r
+{\r
+\r
+  EFI_STATUS   Status;\r
+  USB_SER_DEV  *UsbSerialDevice;\r
+\r
+  UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);\r
+\r
+  Status = SetAttributesInternal (\r
+             UsbSerialDevice,\r
+             BaudRate,\r
+             ReceiveFifoDepth,\r
+             Timeout,\r
+             Parity,\r
+             DataBits,\r
+             StopBits\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Retrieves the status of the control bits on a serial device.\r
+\r
+  @param  This[in]               Protocol instance pointer.\r
+  @param  Control[out]           A pointer to return the current Control signals\r
+                                 from the serial device.\r
+\r
+  @retval EFI_SUCCESS            The control bits were read from the serial\r
+                                 device.\r
+  @retval EFI_DEVICE_ERROR       The serial device is not functioning correctly.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetControlBits (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This,\r
+  OUT UINT32                 *Control\r
+  )\r
+{\r
+  USB_SER_DEV  *UsbSerialDevice;\r
+  EFI_STATUS   Status;\r
+\r
+  UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);\r
+\r
+  *Control        = 0;\r
+\r
+  Status = GetControlBitsInternal (UsbSerialDevice, Control);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Reads data from a serial device.\r
+\r
+  @param  This[in]                   Protocol instance pointer.\r
+  @param  BufferSize[in, out]        On input, the size of the Buffer. On output,\r
+                                     the amount of data returned in Buffer.\r
+  @param  Buffer[out]                The buffer to return the data into.\r
+\r
+  @retval EFI_SUCCESS                The data was read.\r
+  @retval EFI_DEVICE_ERROR           The device reported an error.\r
+  @retval EFI_TIMEOUT                The data write was stopped due to a timeout.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ReadSerialIo (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This,\r
+  IN OUT UINTN               *BufferSize,\r
+  OUT VOID                   *Buffer\r
+  )\r
+{\r
+  UINTN        Index;\r
+  UINTN        RemainingCallerBufferSize;\r
+  USB_SER_DEV  *UsbSerialDevice;\r
+  EFI_STATUS   Status;\r
+\r
+\r
+  if (*BufferSize == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (Buffer == NULL) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  Status          = EFI_SUCCESS;\r
+  UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);\r
+\r
+  //\r
+  // Clear out any data that we already have in our internal buffer\r
+  //\r
+  for (Index = 0; Index < *BufferSize; Index++) {\r
+    if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Still have characters in the buffer to return\r
+    //\r
+    ((UINT8 *)Buffer)[Index] = UsbSerialDevice->DataBuffer[UsbSerialDevice->DataBufferHead];\r
+    UsbSerialDevice->DataBufferHead = (UsbSerialDevice->DataBufferHead + 1) % SW_FIFO_DEPTH;\r
+  }\r
+\r
+  //\r
+  // If we haven't filled the caller's buffer using data that we already had on\r
+  // hand We need to generate an additional USB request to try and fill the\r
+  // caller's buffer\r
+  //\r
+  if (Index != *BufferSize) {\r
+    RemainingCallerBufferSize = *BufferSize - Index;\r
+    Status = ReadDataFromUsb (\r
+               UsbSerialDevice,\r
+               &RemainingCallerBufferSize,\r
+               (VOID *)(((CHAR8 *)Buffer) + Index)\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      *BufferSize = RemainingCallerBufferSize + Index;\r
+    } else {\r
+      *BufferSize = Index;\r
+    }\r
+  }\r
+\r
+  if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {\r
+    //\r
+    // Data buffer has no data, set the EFI_SERIAL_INPUT_BUFFER_EMPTY flag\r
+    //\r
+    UsbSerialDevice->ControlBits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;\r
+  } else {\r
+    //\r
+    // There is some leftover data, clear EFI_SERIAL_INPUT_BUFFER_EMPTY flag\r
+    //\r
+    UsbSerialDevice->ControlBits &= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY);\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Writes data to a serial device.\r
+\r
+  @param  This[in]                   Protocol instance pointer.\r
+  @param  BufferSize[in, out]        On input, the size of the Buffer. On output,\r
+                                     the amount of data actually written.\r
+  @param  Buffer[in]                 The buffer of data to write\r
+\r
+  @retval EFI_SUCCESS                The data was written.\r
+  @retval EFI_DEVICE_ERROR           The device reported an error.\r
+  @retval EFI_TIMEOUT                The data write was stopped due to a timeout.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+WriteSerialIo (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This,\r
+  IN OUT UINTN               *BufferSize,\r
+  IN VOID                    *Buffer\r
+  )\r
+{\r
+  EFI_STATUS   Status;\r
+  USB_SER_DEV  *UsbSerialDevice;\r
+  EFI_TPL      Tpl;\r
+\r
+  UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);\r
+\r
+  if (UsbSerialDevice->Shutdown) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+  Status = UsbSerialDataTransfer (\r
+             UsbSerialDevice,\r
+             EfiUsbDataOut,\r
+             Buffer,\r
+             BufferSize,\r
+             FTDI_TIMEOUT\r
+             );\r
+\r
+  gBS->RestoreTPL (Tpl);\r
+  if (EFI_ERROR (Status)) {\r
+    if (Status == EFI_TIMEOUT){\r
+      return Status;\r
+    } else {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.h b/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.h
new file mode 100644 (file)
index 0000000..07f4133
--- /dev/null
@@ -0,0 +1,595 @@
+/** @file\r
+  Header file for USB Serial Driver's Data Structures.\r
+\r
+Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.\r
+Portions Copyright 2012 Ashley DeSimone\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD\r
+License which accompanies this distribution.  The full text of the license may\r
+be found at http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _FTDI_USB_SERIAL_DRIVER_H_\r
+#define _FTDI_USB_SERIAL_DRIVER_H_\r
+\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DevicePathLib.h>\r
+\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/UsbIo.h>\r
+#include <Protocol/SerialIo.h>\r
+\r
+//\r
+// US English LangID\r
+//\r
+#define USB_US_LANG_ID  0x0409\r
+\r
+//\r
+// Supported Vendor Ids\r
+//\r
+#define VID_FTDI    0x0403\r
+\r
+//\r
+// Supported product ids\r
+//\r
+#define DID_FTDI_FT232    0x6001\r
+\r
+//\r
+// FTDI Commands\r
+//\r
+#define FTDI_COMMAND_RESET_PORT          0\r
+#define FTDI_COMMAND_MODEM_CTRL          1\r
+#define FTDI_COMMAND_SET_FLOW_CTRL       2\r
+#define FTDI_COMMAND_SET_BAUDRATE        3\r
+#define FTDI_COMMAND_SET_DATA            4\r
+#define FTDI_COMMAND_GET_MODEM_STATUS    5\r
+#define FTDI_COMMAND_SET_EVENT_CHAR      6\r
+#define FTDI_COMMAND_SET_ERROR_CHAR      7\r
+#define FTDI_COMMAND_SET_LATENCY_TIMER   9\r
+#define FTDI_COMMAND_GET_LATENCY_TIMER   10\r
+\r
+//\r
+// FTDI_PORT_IDENTIFIER\r
+// Used in the usb control transfers that issue FTDI commands as the index value.\r
+//\r
+#define FTDI_PORT_IDENTIFIER    0x1 // For FTDI USB serial adapter the port\r
+                                    // identifier is always 1.\r
+\r
+//\r
+// RESET_PORT\r
+//\r
+#define RESET_PORT_RESET        0x0 // Purges RX and TX, clears DTR and RTS sets\r
+                                    // flow control to none, disables event\r
+                                    // trigger, sets the event char to 0x0d and\r
+                                    // does nothing to baudrate or data settings\r
+#define RESET_PORT_PURGE_RX     0x1\r
+#define RESET_PORT_PURGE_TX     0x2\r
+\r
+//\r
+// SET_FLOW_CONTROL\r
+//\r
+#define NO_FLOW_CTRL                     0x0\r
+#define XON_XOFF_CTRL                    0x4\r
+\r
+//\r
+// SET_BAUD_RATE\r
+// To set baud rate, one must calculate an encoding of the baud rate from\r
+// UINT32 to UINT16.See EncodeBaudRateForFtdi() for details\r
+//\r
+#define FTDI_UART_FREQUENCY              3000000\r
+#define FTDI_MIN_DIVISOR                 0x20\r
+#define FTDI_MAX_DIVISOR                 0x3FFF8\r
+//\r
+// Special case baudrate values\r
+// 300,000 and 200,000 are special cases for calculating the encoded baudrate\r
+//\r
+#define FTDI_SPECIAL_CASE_300_MIN        (3000000 * 100) / 103 // minimum adjusted\r
+                                                               // value for 300,000\r
+#define FTDI_SPECIAL_CASE_300_MAX        (3000000 * 100) / 97  // maximum adjusted\r
+                                                               // value for 300,000\r
+#define FTDI_SPECIAL_CASE_200_MIN        (2000000 * 100) / 103 // minimum adjusted\r
+                                                               // value for 200,000\r
+#define FTDI_SPECIAL_CASE_200_MAX        (2000000 * 100) / 97  // maximum adjusted\r
+                                                               // value for 200,000\r
+//\r
+// Min and max frequency values that the FTDI chip can attain\r
+//.all generated frequencies must be between these values\r
+//\r
+#define FTDI_MIN_FREQUENCY              46601941 // (3MHz * 1600) / 103 = 46601941\r
+#define FTDI_MAX_FREQUENCY              49484536 // (3MHz * 1600) / 97 = 49484536\r
+\r
+//\r
+// SET_DATA_BITS\r
+//\r
+#define SET_DATA_BITS(n)                 (n)\r
+\r
+//\r
+// SET_PARITY\r
+//\r
+#define SET_PARITY_NONE                   0x0\r
+#define SET_PARITY_ODD                    BIT8 // (0x1 << 8)\r
+#define SET_PARITY_EVEN                   BIT9 // (0x2 << 8)\r
+#define SET_PARITY_MARK                   BIT9 | BIT8 // (0x3 << 8)\r
+#define SET_PARITY_SPACE                  BIT10 // (0x4 << 8)\r
+\r
+//\r
+// SET_STOP_BITS\r
+//\r
+#define SET_STOP_BITS_1                   0x0\r
+#define SET_STOP_BITS_15                  BIT11 // (0x1 << 11)\r
+#define SET_STOP_BITS_2                   BIT12 // (0x2 << 11)\r
+\r
+//\r
+// SET_MODEM_CTRL\r
+// SET_DTR_HIGH = (1 | (1 << 8)), SET_DTR_LOW = (0 | (1 << 8)\r
+// SET_RTS_HIGH = (2 | (2 << 8)), SET_RTS_LOW = (0 | (2 << 8)\r
+//\r
+#define SET_DTR_HIGH                     (BIT8 | BIT0)\r
+#define SET_DTR_LOW                      (BIT8)\r
+#define SET_RTS_HIGH                     (BIT9 | BIT1)\r
+#define SET_RTS_LOW                      (BIT9)\r
+\r
+//\r
+// MODEM_STATUS\r
+//\r
+#define CTS_MASK                         BIT4\r
+#define DSR_MASK                         BIT5\r
+#define RI_MASK                          BIT6\r
+#define SD_MASK                          BIT7\r
+#define MSR_MASK                         (CTS_MASK | DSR_MASK | RI_MASK | SD_MASK)\r
+\r
+//\r
+// Macro used to check for USB transfer errors\r
+//\r
+#define USB_IS_ERROR(Result, Error)           (((Result) & (Error)) != 0)\r
+\r
+//\r
+// USB request timeouts\r
+//\r
+#define WDR_TIMEOUT        5000  // default urb timeout in ms\r
+#define WDR_SHORT_TIMEOUT  1000  // shorter urb timeout in ms\r
+\r
+//\r
+// FTDI timeout\r
+//\r
+#define FTDI_TIMEOUT       16\r
+\r
+//\r
+// FTDI FIFO depth\r
+//\r
+#define FTDI_MAX_RECEIVE_FIFO_DEPTH  384\r
+\r
+//\r
+// FTDI Endpoint Descriptors\r
+//\r
+#define FTDI_ENDPOINT_ADDRESS_IN   0x81 //the endpoint address for the in enpoint generated by the device\r
+#define FTDI_ENDPOINT_ADDRESS_OUT  0x02 //the endpoint address for the out endpoint generated by the device\r
+\r
+//\r
+// Max buffer size for USB transfers\r
+//\r
+#define SW_FIFO_DEPTH 1024\r
+\r
+//\r
+// struct to define a usb device as a vendor and product id pair\r
+//\r
+typedef struct {\r
+  UINTN     VendorId;\r
+  UINTN     DeviceId;\r
+} USB_DEVICE;\r
+\r
+//\r
+//struct to describe the control bits of the device\r
+//true indicates enabled\r
+//false indicates disabled\r
+// \r
+typedef struct {\r
+  BOOLEAN    HardwareFlowControl;\r
+  BOOLEAN    DtrState;\r
+  BOOLEAN    RtsState;\r
+  BOOLEAN    HardwareLoopBack;\r
+  BOOLEAN    SoftwareLoopBack;\r
+} CONTROL_BITS;\r
+\r
+//\r
+//struct to describe the status bits of the device \r
+//true indicates enabled\r
+//false indicated disabled\r
+//\r
+typedef struct {\r
+  BOOLEAN    CtsState;\r
+  BOOLEAN    DsrState;\r
+  BOOLEAN    RiState;\r
+  BOOLEAN    SdState;\r
+} STATUS_BITS;\r
+\r
+//\r
+// Structure to describe the last attributes of the Usb Serial device\r
+//\r
+typedef struct {\r
+  UINT64              BaudRate;\r
+  UINT32              ReceiveFifoDepth;\r
+  UINT32              Timeout;\r
+  EFI_PARITY_TYPE     Parity;\r
+  UINT8               DataBits;\r
+  EFI_STOP_BITS_TYPE  StopBits;\r
+} PREVIOUS_ATTRIBUTES;\r
+\r
+//\r
+// Structure to describe USB serial device\r
+//\r
+#define USB_SER_DEV_SIGNATURE  SIGNATURE_32 ('u', 's', 'b', 's')\r
+\r
+typedef struct {\r
+  UINTN                         Signature;\r
+  EFI_HANDLE                    ControllerHandle;\r
+  EFI_DEVICE_PATH_PROTOCOL      *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL      *ParentDevicePath;\r
+  UART_DEVICE_PATH              UartDevicePath;\r
+  UART_FLOW_CONTROL_DEVICE_PATH FlowControlDevicePath;\r
+  EFI_USB_IO_PROTOCOL           *UsbIo;\r
+  EFI_USB_INTERFACE_DESCRIPTOR  InterfaceDescriptor;\r
+  EFI_USB_ENDPOINT_DESCRIPTOR   InEndpointDescriptor;\r
+  EFI_USB_ENDPOINT_DESCRIPTOR   OutEndpointDescriptor;\r
+  EFI_UNICODE_STRING_TABLE      *ControllerNameTable;\r
+  UINT32                        DataBufferHead;\r
+  UINT32                        DataBufferTail;\r
+  UINT8                         *DataBuffer;\r
+  EFI_SERIAL_IO_PROTOCOL        SerialIo;\r
+  BOOLEAN                       Shutdown;\r
+  EFI_EVENT                     PollingLoop;\r
+  UINT32                        ControlBits;\r
+  PREVIOUS_ATTRIBUTES           LastSettings;\r
+  CONTROL_BITS                  ControlValues;\r
+  STATUS_BITS                   StatusValues;\r
+  UINT8                         ReadBuffer[512];\r
+} USB_SER_DEV;\r
+\r
+#define USB_SER_DEV_FROM_THIS(a) \\r
+  CR(a, USB_SER_DEV, SerialIo, USB_SER_DEV_SIGNATURE)\r
+\r
+//\r
+// Global Variables\r
+//\r
+extern EFI_DRIVER_BINDING_PROTOCOL   gUsbSerialDriverBinding;\r
+extern EFI_COMPONENT_NAME_PROTOCOL   gUsbSerialComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL  gUsbSerialComponentName2;\r
+\r
+//\r
+// Functions of Driver Binding Protocol\r
+//\r
+/**\r
+  Check whether USB Serial driver supports this device.\r
+\r
+  @param  This[in]                   The USB Serial driver binding protocol.\r
+  @param  Controller[in]             The controller handle to check.\r
+  @param  RemainingDevicePath[in]    The remaining device path.\r
+\r
+  @retval EFI_SUCCESS                The driver supports this controller.\r
+  @retval other                      This device isn't supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbSerialDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  );\r
+\r
+/**\r
+  Starts the Serial device with this driver.\r
+\r
+  This function produces Serial IO Protocol and initializes the USB\r
+  Serial device to manage this USB Serial device.\r
+\r
+  @param  This[in]                   The USB Serial driver binding instance.\r
+  @param  Controller[in]             Handle of device to bind driver to.\r
+  @param  RemainingDevicePath[in]    Optional parameter use to pick a specific\r
+                                     child device to start.\r
+\r
+  @retval EFI_SUCCESS                The controller is controlled by the USB\r
+                                     Serial driver.\r
+  @retval EFI_UNSUPPORTED            No interrupt endpoint can be found.\r
+  @retval Other                      This controller cannot be started.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbSerialDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  );\r
+\r
+/**\r
+  Stop the USB Serial device handled by this driver.\r
+\r
+  @param  This[in]                   The USB Serial driver binding protocol.\r
+  @param  Controller[in]             The controller to release.\r
+  @param  NumberOfChildren[in]       The number of handles in ChildHandleBuffer.\r
+  @param  ChildHandleBuffer[in]      The array of child handle.\r
+\r
+  @retval EFI_SUCCESS                The device was stopped.\r
+  @retval EFI_UNSUPPORTED            Simple Text In Protocol or Simple Text In Ex\r
+                                     Protocol is not installed on Controller.\r
+  @retval EFI_DEVICE_ERROR           The device could not be stopped due to a\r
+                                     device error.\r
+  @retval Others                     Fail to uninstall protocols attached on the\r
+                                     device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbSerialDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   Controller,\r
+  IN  UINTN                        NumberOfChildren,\r
+  IN  EFI_HANDLE                   *ChildHandleBuffer\r
+  );\r
+\r
+//\r
+// Serial IO Member Functions\r
+//\r
+\r
+/**\r
+  Writes data to a serial device.\r
+\r
+  @param  This[in]                   Protocol instance pointer.\r
+  @param  BufferSize[in, out]        On input, the size of the Buffer. On output,\r
+                                     the amount of data actually written.\r
+  @param  Buffer[in]                 The buffer of data to write\r
+\r
+  @retval EFI_SUCCESS                The data was written.\r
+  @retval EFI_DEVICE_ERROR           The device reported an error.\r
+  @retval EFI_TIMEOUT                The data write was stopped due to a timeout.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+WriteSerialIo (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This,\r
+  IN OUT UINTN               *BufferSize,\r
+  IN VOID                    *Buffer\r
+  );\r
+\r
+/**\r
+  Reads data from a serial device.\r
+\r
+  @param  This[in]                   Protocol instance pointer.\r
+  @param  BufferSize[in, out]        On input, the size of the Buffer. On output,\r
+                                     the amount of data returned in Buffer.\r
+  @param  Buffer[out]                The buffer to return the data into.\r
+\r
+  @retval EFI_SUCCESS                The data was read.\r
+  @retval EFI_DEVICE_ERROR           The device reported an error.\r
+  @retval EFI_TIMEOUT                The data write was stopped due to a timeout.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ReadSerialIo (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This,\r
+  IN OUT UINTN               *BufferSize,\r
+  OUT VOID                   *Buffer\r
+  );\r
+\r
+/**\r
+  Retrieves the status of the control bits on a serial device.\r
+\r
+  @param  This[in]               Protocol instance pointer.\r
+  @param  Control[out]           A pointer to return the current Control signals\r
+                                 from the serial device.\r
+\r
+  @retval EFI_SUCCESS            The control bits were read from the serial\r
+                                 device.\r
+  @retval EFI_DEVICE_ERROR       The serial device is not functioning correctly.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetControlBits (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This,\r
+  OUT UINT32                 *Control\r
+  );\r
+\r
+/**\r
+  Set the control bits on a serial device.\r
+\r
+  @param  This[in]             Protocol instance pointer.\r
+  @param  Control[in]          Set the bits of Control that are settable.\r
+\r
+  @retval EFI_SUCCESS          The new control bits were set on the serial device.\r
+  @retval EFI_UNSUPPORTED      The serial device does not support this operation.\r
+  @retval EFI_DEVICE_ERROR     The serial device is not functioning correctly.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetControlBits (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This,\r
+  IN UINT32                  Control\r
+  );\r
+\r
+/**\r
+  Calls SetAttributesInternal() to set the baud rate, receive FIFO depth,\r
+  transmit/receice time out, parity, data buts, and stop bits on a serial device.\r
+\r
+  @param  This[in]             Protocol instance pointer.\r
+  @param  BaudRate[in]         The requested baud rate. A BaudRate value of 0\r
+                               will use the device's default interface speed.\r
+  @param  ReveiveFifoDepth[in] The requested depth of the FIFO on the receive\r
+                               side of the serial interface. A ReceiveFifoDepth\r
+                               value of 0 will use the device's default FIFO\r
+                               depth.\r
+  @param  Timeout[in]          The requested time out for a single character in\r
+                               microseconds.This timeout applies to both the\r
+                               transmit and receive side of the interface.A\r
+                               Timeout value of 0 will use the device's default\r
+                               time out value.\r
+  @param  Parity[in]           The type of parity to use on this serial device.A\r
+                               Parity value of DefaultParity will use the\r
+                               device's default parity value.\r
+  @param  DataBits[in]         The number of data bits to use on the serial\r
+                               device. A DataBits value of 0 will use the\r
+                               device's default data bit setting.\r
+  @param  StopBits[in]         The number of stop bits to use on this serial\r
+                               device. A StopBits value of DefaultStopBits will\r
+                               use the device's default number of stop bits.\r
+\r
+  @retval EFI_SUCCESS          The attributes were set\r
+  @retval EFI_DEVICE_ERROR     The attributes were not able to be\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetAttributes (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This,\r
+  IN UINT64                  BaudRate,\r
+  IN UINT32                  ReceiveFifoDepth,\r
+  IN UINT32                  Timeout,\r
+  IN EFI_PARITY_TYPE         Parity,\r
+  IN UINT8                   DataBits,\r
+  IN EFI_STOP_BITS_TYPE      StopBits\r
+  );\r
+\r
+/**\r
+  Reset the serial device.\r
+\r
+  @param  This              Protocol instance pointer.\r
+\r
+  @retval EFI_SUCCESS       The device was reset.\r
+  @retval EFI_DEVICE_ERROR  The serial device could not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SerialReset (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This\r
+  );\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language,\r
+  then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]                   A pointer to the EFI_COMPONENT_NAME2_PROTOCOL\r
+                                     or EFI_COMPONENT_NAME_PROTOCOL instance.\r
+  @param  Language[in]               A pointer to a Null-terminated ASCII string\r
+                                     array indicating the language. This is the\r
+                                     language of the driver name that the caller\r
+                                     is requesting, and it must match one of the\r
+                                     languages specified in SupportedLanguages.\r
+                                     The number of languages supported by a\r
+                                     driver is up to the driver writer. Language\r
+                                     is specified in RFC 4646 or ISO 639-2\r
+                                     language code format.\r
+  @param  DriverName[out]            A pointer to the Unicode string to return.\r
+                                     This Unicode string is the name of the\r
+                                     driver specified by This in the language\r
+                                     specified by Language.\r
+\r
+  @retval EFI_SUCCESS                The Unicode string for the Driver specified\r
+                                     by This and the language specified by\r
+                                     Language was returned in DriverName.\r
+  @retval EFI_INVALID_PARAMETER      Language is NULL.\r
+  @retval EFI_INVALID_PARAMETER      DriverName is NULL.\r
+  @retval EFI_UNSUPPORTED            The driver specified by This does not\r
+                                     support the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbSerialComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,\r
+  IN  CHAR8                         *Language,\r
+  OUT CHAR16                        **DriverName\r
+  );\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified by\r
+  Language, then a pointer to the controller name is returned in ControllerName,\r
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently\r
+  managing the controller specified by ControllerHandle and ChildHandle,\r
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not\r
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]                   A pointer to the EFI_COMPONENT_NAME2_PROTOCOL\r
+                                     or EFI_COMPONENT_NAME_PROTOCOL instance.\r
+  @param  ControllerHandle[in]       The handle of a controller that the driver\r
+                                     specified by This is managing.  This handle\r
+                                     specifies the controller whose name is to\r
+                                     be returned.\r
+  @param  ChildHandle[in]            The handle of the child controller to\r
+                                     retrieve the name of. This is an optional\r
+                                     parameter that may be NULL. It will be NULL\r
+                                     for device drivers. It will also be NULL\r
+                                     for a bus drivers that wish to retrieve the\r
+                                     name of the bus controller. It will not be\r
+                                     NULL for a bus driver that wishes to\r
+                                     retrieve the name of a child controller.\r
+  @param  Language[in]               A pointer to a Null-terminated ASCII string\r
+                                     array indicating the language.  This is the\r
+                                     language of the driver name that the caller\r
+                                     is requesting, and it must match one of the\r
+                                     languages specified in SupportedLanguages.\r
+                                     The number of languages supported by a\r
+                                     driver is up to the driver writer. Language\r
+                                     is specified in RFC 4646 or ISO 639-2\r
+                                     language code format.\r
+  @param  ControllerName[out]        A pointer to the Unicode string to return.\r
+                                     This Unicode string is the name of the\r
+                                     controller specified by ControllerHandle\r
+                                     and ChildHandle in the language specified\r
+                                     by Language from the point of view of the\r
+                                     driver specified by This.\r
+\r
+  @retval EFI_SUCCESS                The Unicode string for the user readable\r
+                                     name in the language specified by Language\r
+                                     for the driver specified by This was\r
+                                     returned in DriverName.\r
+  @retval EFI_INVALID_PARAMETER      ControllerHandle is not a valid EFI_HANDLE.\r
+  @retval EFI_INVALID_PARAMETER      ChildHandle is not NULL and it is not a\r
+                                     valid EFI_HANDLE.\r
+  @retval EFI_INVALID_PARAMETER      Language is NULL.\r
+  @retval EFI_INVALID_PARAMETER      ControllerName is NULL.\r
+  @retval EFI_UNSUPPORTED            The driver specified by This is not\r
+                                     currently managing the controller specified\r
+                                     by ControllerHandle and ChildHandle.\r
+  @retval EFI_UNSUPPORTED            The driver specified by This does not\r
+                                     support the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbSerialComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                    ControllerHandle,\r
+  IN  EFI_HANDLE                    ChildHandle      OPTIONAL,\r
+  IN  CHAR8                         *Language,\r
+  OUT CHAR16                        **ControllerName\r
+  );\r
+\r
+#endif\r
diff --git a/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDxe.inf b/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDxe.inf
new file mode 100644 (file)
index 0000000..e0381b1
--- /dev/null
@@ -0,0 +1,61 @@
+## @file\r
+#  USB Serial Driver that manages USB Serial device and produces Serial IO\r
+#  Protocol.\r
+#\r
+#  USB Serial Driver consumes USB I/O Protocol and Device Path Protocol, and\r
+#  produces Serial IO Protocol on USB Serial devices.\r
+#  It manages the USB Serial device via USB Bulk Transfer of USB I/O Protocol.\r
+#  This module refers to following specifications:\r
+#  1. UEFI Specification, v2.1\r
+#\r
+# Copyright (c) 2006 - 2013, 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\r
+# License which accompanies this distribution. The full text of the license may\r
+# be found at http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = FtdiUsbSerialDxe\r
+  FILE_GUID                      = A8154B55-2021-4D40-AE81-2E23A02dCC46\r
+  MODULE_TYPE                    = UEFI_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = FtdiUsbSerialEntryPoint\r
+  UNLOAD_IMAGE                   = FtdiUsbSerialUnload\r
+\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  FtdiUsbSerialDriver.c\r
+  FtdiUsbSerialDriver.h\r
+  ComponentName.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiDriverEntryPoint\r
+  BaseMemoryLib\r
+  DebugLib\r
+  MemoryAllocationLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\r
+  DevicePathLib\r
+\r
+[Guids]\r
+  gEfiUartDevicePathGuid\r
+\r
+[Protocols]\r
+  ## TO_START\r
+  ## BY_START\r
+  gEfiDevicePathProtocolGuid\r
+  gEfiUsbIoProtocolGuid                         ## TO_START\r
+  gEfiSerialIoProtocolGuid                      ## BY_START\r
diff --git a/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/ReadMe.txt b/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/ReadMe.txt
new file mode 100644 (file)
index 0000000..d8ca227
--- /dev/null
@@ -0,0 +1,32 @@
+\r
+=== FTDI USB SERIAL OVERVIEW ===\r
+\r
+This is a bus driver that enables the EfiSerialIoProtocol interface\r
+for FTDI8U232AM based USB-to-Serial adapters.\r
+\r
+=== STATUS ===\r
+\r
+Serial Input: Functional on real hardware.\r
+Serial Output: Functional on real hardware.\r
+\r
+Operating Modes: Currently the user is able to change all operating modes\r
+except timeout and FIFO depth.\r
+The default operating mode is:\r
+       Baudrate:     115200\r
+       Parity:       None\r
+       Flow Control: None\r
+       Data Bits:    8\r
+       Stop Bits:    1\r
+Notes: \r
+       Data Bits setting of 6,7,8 can not be combined with a Stop Bits setting of 1.5\r
+\r
+        At baudrates less than 9600 some of the characters may be transmitted incorrectly.\r
+\r
+=== COMPATIBILITY ===\r
+\r
+Tested with:\r
+An FTDI8U232AM based USB-To-Serial adapter, the UEFI Shell, and the SerialTest application \r
+using a PuTTY Terminal\r
+\r
+See CompatibleDevices.txt for a list of devices which have been confirmed to work with this \r
+driver.
\ No newline at end of file
index 4fdcf6d9b35041316cc2166be8635950e2f9230a..afd704612608626d400c2a1c0de17bfd89133296 100644 (file)
   OptionRomPkg/AtapiPassThruDxe/AtapiPassThruDxe.inf\r
   OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430Dxe.inf\r
   OptionRomPkg/UndiRuntimeDxe/UndiRuntimeDxe.inf\r
   OptionRomPkg/AtapiPassThruDxe/AtapiPassThruDxe.inf\r
   OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430Dxe.inf\r
   OptionRomPkg/UndiRuntimeDxe/UndiRuntimeDxe.inf\r
+  OptionRomPkg/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDxe.inf\r
 \r
 [Components.IA32, Components.X64, Components.IPF]\r
   OptionRomPkg/Application/BltLibSample/BltLibSample.inf\r
 \r
 [Components.IA32, Components.X64, Components.IPF]\r
   OptionRomPkg/Application/BltLibSample/BltLibSample.inf\r