Home | History | Annotate | Download | only in WinNtSerialIoDxe
      1 /**@file
      2 
      3 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13 
     14   WinNtSerialIo.c
     15 
     16 Abstract:
     17 
     18   Our DriverBinding member functions operate on the handles
     19   created by the NT Bus driver.
     20 
     21   Handle(1) - WinNtIo - DevicePath(1)
     22 
     23   If a serial port is added to the system this driver creates a new handle.
     24   The new handle is required, since the serial device must add an UART device
     25   pathnode.
     26 
     27   Handle(2) - SerialIo - DevicePath(1)\UART
     28 
     29   The driver then adds a gEfiWinNtSerialPortGuid as a protocol to Handle(1).
     30   The instance data for this protocol is the private data used to create
     31   Handle(2).
     32 
     33   Handle(1) - WinNtIo - DevicePath(1) - WinNtSerialPort
     34 
     35   If the driver is unloaded Handle(2) is removed from the system and
     36   gEfiWinNtSerialPortGuid is removed from Handle(1).
     37 
     38   Note: Handle(1) is any handle created by the Win NT Bus driver that is passed
     39   into the DriverBinding member functions of this driver. This driver requires
     40   a Handle(1) to contain a WinNtIo protocol, a DevicePath protocol, and
     41   the TypeGuid in the WinNtIo must be gEfiWinNtSerialPortGuid.
     42 
     43   If Handle(1) contains a gEfiWinNtSerialPortGuid protocol then the driver is
     44   loaded on the device.
     45 
     46 **/
     47 
     48 #include "WinNtSerialIo.h"
     49 
     50 EFI_DRIVER_BINDING_PROTOCOL gWinNtSerialIoDriverBinding = {
     51   WinNtSerialIoDriverBindingSupported,
     52   WinNtSerialIoDriverBindingStart,
     53   WinNtSerialIoDriverBindingStop,
     54   0xa,
     55   NULL,
     56   NULL
     57 };
     58 
     59 //
     60 // List of supported baud rate
     61 //
     62 UINT64 mBaudRateCurrentSupport[] = {50, 75, 110, 134, 150, 300, 600, 1200, 1800, 2000, 2400, 3600, 4800, 7200, 9600, 19200, 38400, 57600, 115200, SERIAL_PORT_MAX_BAUD_RATE + 1};
     63 
     64 /**
     65   Check the device path node whether it's the Flow Control node or not.
     66 
     67   @param[in] FlowControl    The device path node to be checked.
     68 
     69   @retval TRUE              It's the Flow Control node.
     70   @retval FALSE             It's not.
     71 
     72 **/
     73 BOOLEAN
     74 IsUartFlowControlNode (
     75   IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl
     76   )
     77 {
     78   return (BOOLEAN) (
     79            (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) &&
     80            (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) &&
     81            (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid))
     82            );
     83 }
     84 
     85 /**
     86   Check the device path node whether it contains Flow Control node or not.
     87 
     88   @param[in] DevicePath     The device path to be checked.
     89 
     90   @retval TRUE              It contains the Flow Control node.
     91   @retval FALSE             It doesn't.
     92 
     93 **/
     94 BOOLEAN
     95 ContainsFlowControl (
     96   IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath
     97   )
     98 {
     99   while (!IsDevicePathEnd (DevicePath)) {
    100     if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) {
    101       return TRUE;
    102     }
    103     DevicePath = NextDevicePathNode (DevicePath);
    104   }
    105 
    106   return FALSE;
    107 }
    108 
    109 /**
    110   The user Entry Point for module WinNtSerialIo. The user code starts with this function.
    111 
    112   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
    113   @param[in] SystemTable    A pointer to the EFI System Table.
    114 
    115   @retval EFI_SUCCESS       The entry point is executed successfully.
    116   @retval other             Some error occurs when executing this entry point.
    117 
    118 **/
    119 EFI_STATUS
    120 EFIAPI
    121 InitializeWinNtSerialIo(
    122   IN EFI_HANDLE           ImageHandle,
    123   IN EFI_SYSTEM_TABLE     *SystemTable
    124   )
    125 {
    126   EFI_STATUS              Status;
    127 
    128   //
    129   // Install driver model protocol(s).
    130   //
    131   Status = EfiLibInstallDriverBindingComponentName2 (
    132              ImageHandle,
    133              SystemTable,
    134              &gWinNtSerialIoDriverBinding,
    135              ImageHandle,
    136              &gWinNtSerialIoComponentName,
    137              &gWinNtSerialIoComponentName2
    138              );
    139   ASSERT_EFI_ERROR (Status);
    140 
    141 
    142   return Status;
    143 }
    144 
    145 EFI_STATUS
    146 EFIAPI
    147 WinNtSerialIoDriverBindingSupported (
    148   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
    149   IN  EFI_HANDLE                    Handle,
    150   IN  EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath
    151   )
    152 /*++
    153 
    154 Routine Description:
    155 
    156 Arguments:
    157 
    158 Returns:
    159 
    160   None
    161 
    162 --*/
    163 // TODO:    This - add argument and description to function comment
    164 // TODO:    Handle - add argument and description to function comment
    165 // TODO:    RemainingDevicePath - add argument and description to function comment
    166 // TODO:    EFI_SUCCESS - add return value to function comment
    167 // TODO:    EFI_SUCCESS - add return value to function comment
    168 {
    169   EFI_STATUS                          Status;
    170   EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;
    171   EFI_WIN_NT_IO_PROTOCOL              *WinNtIo;
    172   UART_DEVICE_PATH                    *UartNode;
    173   EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
    174   UART_FLOW_CONTROL_DEVICE_PATH       *FlowControlNode;
    175   EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
    176   UINTN                               EntryCount;
    177   UINTN                               Index;
    178   BOOLEAN                             RemainingDevicePathContainsFlowControl;
    179 
    180   //
    181   // Check RemainingDevicePath validation
    182   //
    183   if (RemainingDevicePath != NULL) {
    184     //
    185     // Check if RemainingDevicePath is the End of Device Path Node,
    186     // if yes, go on checking other conditions
    187     //
    188     if (!IsDevicePathEnd (RemainingDevicePath)) {
    189       //
    190       // If RemainingDevicePath isn't the End of Device Path Node,
    191       // check its validation
    192       //
    193       Status = EFI_UNSUPPORTED;
    194 
    195       UartNode  = (UART_DEVICE_PATH *) RemainingDevicePath;
    196       if (UartNode->Header.Type != MESSAGING_DEVICE_PATH ||
    197           UartNode->Header.SubType != MSG_UART_DP ||
    198           DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL *)UartNode) != sizeof(UART_DEVICE_PATH)) {
    199         goto Error;
    200       }
    201       if ( UartNode->BaudRate > SERIAL_PORT_MAX_BAUD_RATE) {
    202         goto Error;
    203       }
    204       if (UartNode->Parity < NoParity || UartNode->Parity > SpaceParity) {
    205         goto Error;
    206       }
    207       if (UartNode->DataBits < 5 || UartNode->DataBits > 8) {
    208         goto Error;
    209       }
    210       if (UartNode->StopBits < OneStopBit || UartNode->StopBits > TwoStopBits) {
    211         goto Error;
    212       }
    213       if ((UartNode->DataBits == 5) && (UartNode->StopBits == TwoStopBits)) {
    214         goto Error;
    215       }
    216       if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) {
    217         goto Error;
    218       }
    219 
    220       FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (UartNode);
    221       if (IsUartFlowControlNode (FlowControlNode)) {
    222         //
    223         // If the second node is Flow Control Node,
    224         //   return error when it request other than hardware flow control.
    225         //
    226         if ((FlowControlNode->FlowControlMap & ~UART_FLOW_CONTROL_HARDWARE) != 0) {
    227           goto Error;
    228         }
    229       }
    230     }
    231   }
    232 
    233   //
    234   // Open the IO Abstraction(s) needed to perform the supported test
    235   //
    236   Status = gBS->OpenProtocol (
    237                   Handle,
    238                   &gEfiWinNtIoProtocolGuid,
    239                   (VOID **) &WinNtIo,
    240                   This->DriverBindingHandle,
    241                   Handle,
    242                   EFI_OPEN_PROTOCOL_BY_DRIVER
    243                   );
    244   if (Status == EFI_ALREADY_STARTED) {
    245     if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
    246       //
    247       // If RemainingDevicePath is NULL or is the End of Device Path Node
    248       //
    249       return EFI_SUCCESS;
    250     }
    251     //
    252     // When the driver has produced device path with flow control node but RemainingDevicePath only contains UART node,
    253     //   return unsupported, and vice versa.
    254     //
    255     Status = gBS->OpenProtocolInformation (
    256                     Handle,
    257                     &gEfiWinNtIoProtocolGuid,
    258                     &OpenInfoBuffer,
    259                     &EntryCount
    260                     );
    261     if (EFI_ERROR (Status)) {
    262       return Status;
    263     }
    264 
    265     //
    266     // See if RemainingDevicePath has a Flow Control device path node
    267     //
    268     RemainingDevicePathContainsFlowControl = ContainsFlowControl (RemainingDevicePath);
    269 
    270     for (Index = 0; Index < EntryCount; Index++) {
    271       if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
    272         Status = gBS->OpenProtocol (
    273                         OpenInfoBuffer[Index].ControllerHandle,
    274                         &gEfiDevicePathProtocolGuid,
    275                         (VOID **) &DevicePath,
    276                         This->DriverBindingHandle,
    277                         Handle,
    278                         EFI_OPEN_PROTOCOL_GET_PROTOCOL
    279                         );
    280         if (!EFI_ERROR (Status)) {
    281           if (RemainingDevicePathContainsFlowControl ^ ContainsFlowControl (DevicePath)) {
    282             Status = EFI_UNSUPPORTED;
    283           }
    284         }
    285         break;
    286       }
    287     }
    288     FreePool (OpenInfoBuffer);
    289     return Status;
    290   }
    291 
    292   if (EFI_ERROR (Status)) {
    293     return Status;
    294   }
    295 
    296   //
    297   // Close the I/O Abstraction(s) used to perform the supported test
    298   //
    299   gBS->CloseProtocol (
    300         Handle,
    301         &gEfiWinNtIoProtocolGuid,
    302         This->DriverBindingHandle,
    303         Handle
    304         );
    305 
    306   //
    307   // Open the EFI Device Path protocol needed to perform the supported test
    308   //
    309   Status = gBS->OpenProtocol (
    310                   Handle,
    311                   &gEfiDevicePathProtocolGuid,
    312                   (VOID **) &ParentDevicePath,
    313                   This->DriverBindingHandle,
    314                   Handle,
    315                   EFI_OPEN_PROTOCOL_BY_DRIVER
    316                   );
    317   if (Status == EFI_ALREADY_STARTED) {
    318     return EFI_SUCCESS;
    319   }
    320 
    321   if (EFI_ERROR (Status)) {
    322     return Status;
    323   }
    324 
    325   //
    326   // Close protocol, don't use device path protocol in the Support() function
    327   //
    328   gBS->CloseProtocol (
    329         Handle,
    330         &gEfiDevicePathProtocolGuid,
    331         This->DriverBindingHandle,
    332         Handle
    333         );
    334 
    335   //
    336   // Make sure that the WinNt Thunk Protocol is valid
    337   //
    338   if (WinNtIo->WinNtThunk->Signature != EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) {
    339     Status = EFI_UNSUPPORTED;
    340     goto Error;
    341   }
    342 
    343   //
    344   // Check the GUID to see if this is a handle type the driver supports
    345   //
    346   if (!CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtSerialPortGuid)) {
    347     Status = EFI_UNSUPPORTED;
    348     goto Error;
    349   }
    350 
    351   return EFI_SUCCESS;
    352 
    353 Error:
    354   return Status;
    355 }
    356 
    357 EFI_STATUS
    358 EFIAPI
    359 WinNtSerialIoDriverBindingStart (
    360   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
    361   IN  EFI_HANDLE                    Handle,
    362   IN  EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath
    363   )
    364 /*++
    365 
    366 Routine Description:
    367 
    368 Arguments:
    369 
    370 Returns:
    371 
    372   None
    373 
    374 --*/
    375 // TODO:    This - add argument and description to function comment
    376 // TODO:    Handle - add argument and description to function comment
    377 // TODO:    RemainingDevicePath - add argument and description to function comment
    378 // TODO:    EFI_SUCCESS - add return value to function comment
    379 // TODO:    EFI_SUCCESS - add return value to function comment
    380 {
    381   EFI_STATUS                          Status;
    382   EFI_WIN_NT_IO_PROTOCOL              *WinNtIo;
    383   WIN_NT_SERIAL_IO_PRIVATE_DATA       *Private;
    384   HANDLE                              NtHandle;
    385   UART_DEVICE_PATH                    UartNode;
    386   EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;
    387   EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
    388   UINTN                               EntryCount;
    389   UINTN                               Index;
    390   EFI_SERIAL_IO_PROTOCOL              *SerialIo;
    391   UART_DEVICE_PATH                    *Uart;
    392   UINT32                              FlowControlMap;
    393   UART_FLOW_CONTROL_DEVICE_PATH       *FlowControl;
    394   EFI_DEVICE_PATH_PROTOCOL            *TempDevicePath;
    395   UINT32                              Control;
    396 
    397   Private   = NULL;
    398   NtHandle  = INVALID_HANDLE_VALUE;
    399 
    400   //
    401   // Get the Parent Device Path
    402   //
    403   Status = gBS->OpenProtocol (
    404                   Handle,
    405                   &gEfiDevicePathProtocolGuid,
    406                   (VOID **) &ParentDevicePath,
    407                   This->DriverBindingHandle,
    408                   Handle,
    409                   EFI_OPEN_PROTOCOL_BY_DRIVER
    410                   );
    411   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
    412     return Status;
    413   }
    414 
    415   //
    416   // Grab the IO abstraction we need to get any work done
    417   //
    418   Status = gBS->OpenProtocol (
    419                   Handle,
    420                   &gEfiWinNtIoProtocolGuid,
    421                   (VOID **) &WinNtIo,
    422                   This->DriverBindingHandle,
    423                   Handle,
    424                   EFI_OPEN_PROTOCOL_BY_DRIVER
    425                   );
    426   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
    427     gBS->CloseProtocol (
    428           Handle,
    429           &gEfiDevicePathProtocolGuid,
    430           This->DriverBindingHandle,
    431           Handle
    432           );
    433     return Status;
    434   }
    435 
    436   if (Status == EFI_ALREADY_STARTED) {
    437 
    438     if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
    439       //
    440       // If RemainingDevicePath is NULL or is the End of Device Path Node
    441       //
    442       return EFI_SUCCESS;
    443     }
    444 
    445     //
    446     // Make sure a child handle does not already exist.  This driver can only
    447     // produce one child per serial port.
    448     //
    449     Status = gBS->OpenProtocolInformation (
    450                     Handle,
    451                     &gEfiWinNtIoProtocolGuid,
    452                     &OpenInfoBuffer,
    453                     &EntryCount
    454                     );
    455     if (EFI_ERROR (Status)) {
    456       return Status;
    457     }
    458 
    459     Status = EFI_ALREADY_STARTED;
    460     for (Index = 0; Index < EntryCount; Index++) {
    461       if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
    462         Status = gBS->OpenProtocol (
    463                         OpenInfoBuffer[Index].ControllerHandle,
    464                         &gEfiSerialIoProtocolGuid,
    465                         (VOID **) &SerialIo,
    466                         This->DriverBindingHandle,
    467                         Handle,
    468                         EFI_OPEN_PROTOCOL_GET_PROTOCOL
    469                         );
    470         if (!EFI_ERROR (Status)) {
    471           Uart   = (UART_DEVICE_PATH *) RemainingDevicePath;
    472           Status = SerialIo->SetAttributes (
    473                                SerialIo,
    474                                Uart->BaudRate,
    475                                SerialIo->Mode->ReceiveFifoDepth,
    476                                SerialIo->Mode->Timeout,
    477                                (EFI_PARITY_TYPE) Uart->Parity,
    478                                Uart->DataBits,
    479                                (EFI_STOP_BITS_TYPE) Uart->StopBits
    480                                );
    481           FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart);
    482           if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) {
    483             Status = SerialIo->GetControl (SerialIo, &Control);
    484             if (!EFI_ERROR (Status)) {
    485               if (FlowControl->FlowControlMap == UART_FLOW_CONTROL_HARDWARE) {
    486                 Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
    487               } else {
    488                 Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
    489               }
    490               //
    491               // Clear the bits that are not allowed to pass to SetControl
    492               //
    493               Control &= (EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |
    494                           EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |
    495                           EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE);
    496               Status = SerialIo->SetControl (SerialIo, Control);
    497             }
    498           }
    499         }
    500         break;
    501       }
    502     }
    503 
    504     FreePool (OpenInfoBuffer);
    505     return Status;
    506   }
    507 
    508   FlowControl    = NULL;
    509   FlowControlMap = 0;
    510   if (RemainingDevicePath == NULL) {
    511     //
    512     // Build the device path by appending the UART node to the ParentDevicePath
    513     // from the WinNtIo handle. The Uart setings are zero here, since
    514     // SetAttribute() will update them to match the default setings.
    515     //
    516     ZeroMem (&UartNode, sizeof (UART_DEVICE_PATH));
    517     UartNode.Header.Type     = MESSAGING_DEVICE_PATH;
    518     UartNode.Header.SubType  = MSG_UART_DP;
    519     SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &UartNode, sizeof (UART_DEVICE_PATH));
    520 
    521   } else if (!IsDevicePathEnd (RemainingDevicePath)) {
    522     //
    523     // If RemainingDevicePath isn't the End of Device Path Node,
    524     // only scan the specified device by RemainingDevicePath
    525     //
    526     //
    527     // Match the configuration of the RemainingDevicePath. IsHandleSupported()
    528     // already checked to make sure the RemainingDevicePath contains settings
    529     // that we can support.
    530     //
    531     CopyMem (&UartNode, RemainingDevicePath, sizeof (UART_DEVICE_PATH));
    532     FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);
    533     if (IsUartFlowControlNode (FlowControl)) {
    534       FlowControlMap = FlowControl->FlowControlMap;
    535     } else {
    536       FlowControl    = NULL;
    537     }
    538 
    539   } else {
    540     //
    541     // If RemainingDevicePath is the End of Device Path Node,
    542     // skip enumerate any device and return EFI_SUCESSS
    543     //
    544     return EFI_SUCCESS;
    545   }
    546 
    547   //
    548   // Check to see if we can access the hardware device. If it's Open in NT we
    549   // will not get access.
    550   //
    551   NtHandle = WinNtIo->WinNtThunk->CreateFile (
    552                                     WinNtIo->EnvString,
    553                                     GENERIC_READ | GENERIC_WRITE,
    554                                     0,
    555                                     NULL,
    556                                     OPEN_EXISTING,
    557                                     0,
    558                                     NULL
    559                                     );
    560   if (NtHandle == INVALID_HANDLE_VALUE) {
    561     Status = EFI_DEVICE_ERROR;
    562     goto Error;
    563   }
    564 
    565   //
    566   // Construct Private data
    567   //
    568   Private = AllocatePool (sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA));
    569   if (Private == NULL) {
    570     goto Error;
    571   }
    572 
    573   //
    574   // This signature must be valid before any member function is called
    575   //
    576   Private->Signature              = WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE;
    577   Private->NtHandle               = NtHandle;
    578   Private->ControllerHandle       = Handle;
    579   Private->Handle                 = NULL;
    580   Private->WinNtThunk             = WinNtIo->WinNtThunk;
    581   Private->ParentDevicePath       = ParentDevicePath;
    582   Private->ControllerNameTable    = NULL;
    583 
    584   Private->SoftwareLoopbackEnable = FALSE;
    585   Private->HardwareLoopbackEnable = FALSE;
    586   Private->HardwareFlowControl    = (BOOLEAN) (FlowControlMap == UART_FLOW_CONTROL_HARDWARE);
    587   Private->Fifo.First             = 0;
    588   Private->Fifo.Last              = 0;
    589   Private->Fifo.Surplus           = SERIAL_MAX_BUFFER_SIZE;
    590 
    591   CopyMem (&Private->UartDevicePath, &UartNode, sizeof (UART_DEVICE_PATH));
    592 
    593   AddUnicodeString2 (
    594     "eng",
    595     gWinNtSerialIoComponentName.SupportedLanguages,
    596     &Private->ControllerNameTable,
    597     WinNtIo->EnvString,
    598     TRUE
    599     );
    600   AddUnicodeString2 (
    601     "en",
    602     gWinNtSerialIoComponentName2.SupportedLanguages,
    603     &Private->ControllerNameTable,
    604     WinNtIo->EnvString,
    605     FALSE
    606     );
    607 
    608 
    609   Private->SerialIo.Revision      = SERIAL_IO_INTERFACE_REVISION;
    610   Private->SerialIo.Reset         = WinNtSerialIoReset;
    611   Private->SerialIo.SetAttributes = WinNtSerialIoSetAttributes;
    612   Private->SerialIo.SetControl    = WinNtSerialIoSetControl;
    613   Private->SerialIo.GetControl    = WinNtSerialIoGetControl;
    614   Private->SerialIo.Write         = WinNtSerialIoWrite;
    615   Private->SerialIo.Read          = WinNtSerialIoRead;
    616   Private->SerialIo.Mode          = &Private->SerialIoMode;
    617 
    618   //
    619   // Build the device path by appending the UART node to the ParentDevicePath
    620   // from the WinNtIo handle. The Uart setings are zero here, since
    621   // SetAttribute() will update them to match the current setings.
    622   //
    623   Private->DevicePath = AppendDevicePathNode (
    624                           ParentDevicePath,
    625                           (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath
    626                           );
    627   //
    628   // Only produce the FlowControl node when remaining device path has it
    629   //
    630   if (FlowControl != NULL) {
    631     TempDevicePath = Private->DevicePath;
    632     if (TempDevicePath != NULL) {
    633       Private->DevicePath = AppendDevicePathNode (
    634                               TempDevicePath,
    635                               (EFI_DEVICE_PATH_PROTOCOL *) FlowControl
    636                               );
    637       FreePool (TempDevicePath);
    638     }
    639   }
    640   if (Private->DevicePath == NULL) {
    641     Status = EFI_OUT_OF_RESOURCES;
    642     goto Error;
    643   }
    644 
    645   //
    646   // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
    647   //
    648   Private->SerialIoMode.ControlMask       = SERIAL_CONTROL_MASK;
    649   Private->SerialIoMode.Timeout           = SERIAL_TIMEOUT_DEFAULT;
    650   Private->SerialIoMode.BaudRate          = Private->UartDevicePath.BaudRate;
    651   Private->SerialIoMode.ReceiveFifoDepth  = SERIAL_FIFO_DEFAULT;
    652   Private->SerialIoMode.DataBits          = Private->UartDevicePath.DataBits;
    653   Private->SerialIoMode.Parity            = Private->UartDevicePath.Parity;
    654   Private->SerialIoMode.StopBits          = Private->UartDevicePath.StopBits;
    655 
    656   //
    657   // Issue a reset to initialize the COM port
    658   //
    659   Status = Private->SerialIo.Reset (&Private->SerialIo);
    660   if (EFI_ERROR (Status)) {
    661     goto Error;
    662   }
    663 
    664   //
    665   // Create new child handle
    666   //
    667   Status = gBS->InstallMultipleProtocolInterfaces (
    668                   &Private->Handle,
    669                   &gEfiSerialIoProtocolGuid,
    670                   &Private->SerialIo,
    671                   &gEfiDevicePathProtocolGuid,
    672                   Private->DevicePath,
    673                   NULL
    674                   );
    675   if (EFI_ERROR (Status)) {
    676     goto Error;
    677   }
    678 
    679   //
    680   // Open For Child Device
    681   //
    682   Status = gBS->OpenProtocol (
    683                   Handle,
    684                   &gEfiWinNtIoProtocolGuid,
    685                   (VOID **) &WinNtIo,
    686                   This->DriverBindingHandle,
    687                   Private->Handle,
    688                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    689                   );
    690   if (EFI_ERROR (Status)) {
    691     goto Error;
    692   }
    693 
    694   return EFI_SUCCESS;
    695 
    696 Error:
    697   //
    698   // Use the Stop() function to free all resources allocated in Start()
    699   //
    700   if (Private != NULL) {
    701     if (Private->Handle != NULL) {
    702       This->Stop (This, Handle, 1, &Private->Handle);
    703     } else {
    704       if (NtHandle != INVALID_HANDLE_VALUE) {
    705         Private->WinNtThunk->CloseHandle (NtHandle);
    706       }
    707 
    708       if (Private->DevicePath != NULL) {
    709         FreePool (Private->DevicePath);
    710       }
    711 
    712       FreeUnicodeStringTable (Private->ControllerNameTable);
    713 
    714       FreePool (Private);
    715     }
    716   }
    717 
    718   This->Stop (This, Handle, 0, NULL);
    719 
    720   return Status;
    721 }
    722 
    723 EFI_STATUS
    724 EFIAPI
    725 WinNtSerialIoDriverBindingStop (
    726   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
    727   IN  EFI_HANDLE                    Handle,
    728   IN  UINTN                         NumberOfChildren,
    729   IN  EFI_HANDLE                    *ChildHandleBuffer
    730   )
    731 /*++
    732 
    733 Routine Description:
    734 
    735   TODO: Add function description
    736 
    737 Arguments:
    738 
    739   This              - TODO: add argument description
    740   Handle            - TODO: add argument description
    741   NumberOfChildren  - TODO: add argument description
    742   ChildHandleBuffer - TODO: add argument description
    743 
    744 Returns:
    745 
    746   EFI_DEVICE_ERROR - TODO: Add description for return value
    747   EFI_SUCCESS - TODO: Add description for return value
    748 
    749 --*/
    750 {
    751   EFI_STATUS                    Status;
    752   UINTN                         Index;
    753   BOOLEAN                       AllChildrenStopped;
    754   EFI_SERIAL_IO_PROTOCOL        *SerialIo;
    755   WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
    756   EFI_WIN_NT_IO_PROTOCOL        *WinNtIo;
    757 
    758   //
    759   // Complete all outstanding transactions to Controller.
    760   // Don't allow any new transaction to Controller to be started.
    761   //
    762 
    763   if (NumberOfChildren == 0) {
    764     //
    765     // Close the bus driver
    766     //
    767     Status = gBS->CloseProtocol (
    768                     Handle,
    769                     &gEfiWinNtIoProtocolGuid,
    770                     This->DriverBindingHandle,
    771                     Handle
    772                     );
    773     Status = gBS->CloseProtocol (
    774                     Handle,
    775                     &gEfiDevicePathProtocolGuid,
    776                     This->DriverBindingHandle,
    777                     Handle
    778                     );
    779     return Status;
    780   }
    781 
    782   AllChildrenStopped = TRUE;
    783 
    784   for (Index = 0; Index < NumberOfChildren; Index++) {
    785     Status = gBS->OpenProtocol (
    786                     ChildHandleBuffer[Index],
    787                     &gEfiSerialIoProtocolGuid,
    788                     (VOID **) &SerialIo,
    789                     This->DriverBindingHandle,
    790                     Handle,
    791                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
    792                     );
    793     if (!EFI_ERROR (Status)) {
    794       Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo);
    795 
    796       ASSERT (Private->Handle == ChildHandleBuffer[Index]);
    797 
    798       Status = gBS->CloseProtocol (
    799                       Handle,
    800                       &gEfiWinNtIoProtocolGuid,
    801                       This->DriverBindingHandle,
    802                       ChildHandleBuffer[Index]
    803                       );
    804 
    805       Status = gBS->UninstallMultipleProtocolInterfaces (
    806                       ChildHandleBuffer[Index],
    807                       &gEfiSerialIoProtocolGuid,
    808                       &Private->SerialIo,
    809                       &gEfiDevicePathProtocolGuid,
    810                       Private->DevicePath,
    811                       NULL
    812                       );
    813 
    814       if (EFI_ERROR (Status)) {
    815         gBS->OpenProtocol (
    816               Handle,
    817               &gEfiWinNtIoProtocolGuid,
    818               (VOID **) &WinNtIo,
    819               This->DriverBindingHandle,
    820               ChildHandleBuffer[Index],
    821               EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    822               );
    823       } else {
    824         Private->WinNtThunk->CloseHandle (Private->NtHandle);
    825 
    826         FreePool (Private->DevicePath);
    827 
    828         FreeUnicodeStringTable (Private->ControllerNameTable);
    829 
    830         FreePool (Private);
    831       }
    832     }
    833 
    834     if (EFI_ERROR (Status)) {
    835       AllChildrenStopped = FALSE;
    836     }
    837   }
    838 
    839   if (!AllChildrenStopped) {
    840     return EFI_DEVICE_ERROR;
    841   }
    842 
    843   return EFI_SUCCESS;
    844 }
    845 
    846 //
    847 // Serial IO Protocol member functions
    848 //
    849 
    850 EFI_STATUS
    851 EFIAPI
    852 WinNtSerialIoReset (
    853   IN EFI_SERIAL_IO_PROTOCOL *This
    854   )
    855 /*++
    856 
    857 Routine Description:
    858 
    859   TODO: Add function description
    860 
    861 Arguments:
    862 
    863   This  - TODO: add argument description
    864 
    865 Returns:
    866 
    867   TODO: add return values
    868 
    869 --*/
    870 {
    871   WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
    872   EFI_TPL                       Tpl;
    873 
    874   Tpl     = gBS->RaiseTPL (TPL_NOTIFY);
    875 
    876   Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
    877 
    878   Private->WinNtThunk->PurgeComm (
    879                         Private->NtHandle,
    880                         PURGE_TXCLEAR | PURGE_RXCLEAR
    881                         );
    882 
    883   gBS->RestoreTPL (Tpl);
    884 
    885   return This->SetAttributes (
    886                 This,
    887                 This->Mode->BaudRate,
    888                 This->Mode->ReceiveFifoDepth,
    889                 This->Mode->Timeout,
    890                 (EFI_PARITY_TYPE)This->Mode->Parity,
    891                 (UINT8) This->Mode->DataBits,
    892                 (EFI_STOP_BITS_TYPE)This->Mode->StopBits
    893                 );
    894 }
    895 
    896 EFI_STATUS
    897 EFIAPI
    898 WinNtSerialIoSetAttributes (
    899   IN EFI_SERIAL_IO_PROTOCOL *This,
    900   IN UINT64                 BaudRate,
    901   IN UINT32                 ReceiveFifoDepth,
    902   IN UINT32                 Timeout,
    903   IN EFI_PARITY_TYPE        Parity,
    904   IN UINT8                  DataBits,
    905   IN EFI_STOP_BITS_TYPE     StopBits
    906   )
    907 /*++
    908 
    909 Routine Description:
    910 
    911   This function is used to set the attributes.
    912 
    913 Arguments:
    914 
    915   This              - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
    916   BaudRate          - The Baud rate of the serial device.
    917   ReceiveFifoDepth  - The request depth of fifo on receive side.
    918   Timeout           - the request timeout for a single charact.
    919   Parity            - The type of parity used in serial device.
    920   DataBits          - Number of deata bits used in serial device.
    921   StopBits          - Number of stop bits used in serial device.
    922 
    923 Returns:
    924   Status code
    925 
    926   None
    927 
    928 --*/
    929 // TODO:    EFI_SUCCESS - add return value to function comment
    930 // TODO:    EFI_DEVICE_ERROR - add return value to function comment
    931 // TODO:    EFI_DEVICE_ERROR - add return value to function comment
    932 // TODO:    EFI_DEVICE_ERROR - add return value to function comment
    933 // TODO:    EFI_SUCCESS - add return value to function comment
    934 // TODO:    EFI_DEVICE_ERROR - add return value to function comment
    935 // TODO:    EFI_SUCCESS - add return value to function comment
    936 {
    937   EFI_STATUS                    Status;
    938   UINTN                         Index;
    939   WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
    940   COMMTIMEOUTS                  PortTimeOuts;
    941   DWORD                         ConvertedTime;
    942   BOOL                          Result;
    943   UART_DEVICE_PATH              *Uart;
    944   EFI_TPL                       Tpl;
    945 
    946   Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
    947 
    948   //
    949   //  Some of our arguments have defaults if a null value is passed in, and
    950   //   we must set the default values if a null argument is passed in.
    951   //
    952   if (BaudRate == 0) {
    953     BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
    954   }
    955 
    956   if (ReceiveFifoDepth == 0) {
    957     ReceiveFifoDepth = SERIAL_FIFO_DEFAULT;
    958   }
    959 
    960   if (Timeout == 0) {
    961     Timeout = SERIAL_TIMEOUT_DEFAULT;
    962   }
    963 
    964   if (Parity == DefaultParity) {
    965     Parity = (EFI_PARITY_TYPE) (PcdGet8 (PcdUartDefaultParity));
    966   }
    967 
    968   if (DataBits == 0) {
    969     DataBits = PcdGet8 (PcdUartDefaultDataBits);
    970   }
    971 
    972   if (StopBits == DefaultStopBits) {
    973     StopBits = (EFI_STOP_BITS_TYPE) PcdGet8 (PcdUartDefaultStopBits);
    974   }
    975 
    976   //
    977   // Make sure all parameters are valid
    978   //
    979   if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) {
    980     return EFI_INVALID_PARAMETER;
    981   }
    982 
    983   //
    984   //The lower baud rate supported by the serial device will be selected without exceeding the unsupported BaudRate parameter
    985   //
    986 
    987   for (Index = 1; Index < (ARRAY_SIZE (mBaudRateCurrentSupport)); Index++) {
    988     if (BaudRate < mBaudRateCurrentSupport[Index]) {
    989       BaudRate = mBaudRateCurrentSupport[Index-1];
    990       break;
    991       }
    992   }
    993 
    994   if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {
    995     return EFI_INVALID_PARAMETER;
    996   }
    997 
    998   if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) {
    999     return EFI_INVALID_PARAMETER;
   1000   }
   1001 
   1002   if ((Parity < NoParity) || (Parity > SpaceParity)) {
   1003     return EFI_INVALID_PARAMETER;
   1004   }
   1005 
   1006   if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) {
   1007     return EFI_INVALID_PARAMETER;
   1008   }
   1009 
   1010   //
   1011   // Now we only support DataBits=7,8.
   1012   //
   1013   if ((DataBits < 7) || (DataBits > 8)) {
   1014     return EFI_INVALID_PARAMETER;
   1015   }
   1016 
   1017   //
   1018   // Now we only support DataBits=7,8.
   1019   // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits.
   1020   //
   1021   if (StopBits == OneFiveStopBits) {
   1022     return EFI_INVALID_PARAMETER;
   1023   }
   1024 
   1025   //
   1026   // See if the new attributes already match the current attributes
   1027   //
   1028   if (Private->UartDevicePath.BaudRate       == BaudRate         &&
   1029       Private->UartDevicePath.DataBits       == DataBits         &&
   1030       Private->UartDevicePath.Parity         == Parity           &&
   1031       Private->UartDevicePath.StopBits       == StopBits         &&
   1032       Private->SerialIoMode.ReceiveFifoDepth == ReceiveFifoDepth &&
   1033       Private->SerialIoMode.Timeout          == Timeout             ) {
   1034     return EFI_SUCCESS;
   1035   }
   1036 
   1037   Tpl     = gBS->RaiseTPL (TPL_NOTIFY);
   1038 
   1039   //
   1040   //  Get current values from NT
   1041   //
   1042   ZeroMem (&Private->NtDCB, sizeof (DCB));
   1043   Private->NtDCB.DCBlength = sizeof (DCB);
   1044 
   1045   if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Private->NtDCB)) {
   1046     Private->NtError = Private->WinNtThunk->GetLastError ();
   1047     DEBUG ((EFI_D_ERROR, "SerialSetAttributes: GetCommState %d\n", Private->NtError));
   1048     gBS->RestoreTPL (Tpl);
   1049     return EFI_DEVICE_ERROR;
   1050   }
   1051 
   1052   //
   1053   // Map EFI com setting to NT
   1054   //
   1055   Private->NtDCB.BaudRate         = ConvertBaud2Nt (BaudRate);
   1056   Private->NtDCB.ByteSize         = ConvertData2Nt (DataBits);
   1057   Private->NtDCB.Parity           = ConvertParity2Nt (Parity);
   1058   Private->NtDCB.StopBits         = ConvertStop2Nt (StopBits);
   1059 
   1060   Private->NtDCB.fBinary          = TRUE;
   1061   Private->NtDCB.fParity          = Private->NtDCB.Parity == NOPARITY ? FALSE : TRUE;
   1062   Private->NtDCB.fOutxCtsFlow     = FALSE;
   1063   Private->NtDCB.fOutxDsrFlow     = FALSE;
   1064   Private->NtDCB.fDtrControl      = DTR_CONTROL_ENABLE;
   1065   Private->NtDCB.fDsrSensitivity  = FALSE;
   1066   Private->NtDCB.fOutX            = FALSE;
   1067   Private->NtDCB.fInX             = FALSE;
   1068   Private->NtDCB.fRtsControl      = RTS_CONTROL_ENABLE;
   1069   Private->NtDCB.fNull            = FALSE;
   1070 
   1071   //
   1072   //  Set new values
   1073   //
   1074   Result = Private->WinNtThunk->SetCommState (Private->NtHandle, &Private->NtDCB);
   1075   if (!Result) {
   1076     Private->NtError = Private->WinNtThunk->GetLastError ();
   1077     DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommState %d\n", Private->NtError));
   1078     gBS->RestoreTPL (Tpl);
   1079     return EFI_DEVICE_ERROR;
   1080   }
   1081 
   1082   //
   1083   //  Set com port read/write timeout values
   1084   //
   1085   ConvertedTime = ConvertTime2Nt (Timeout);
   1086   PortTimeOuts.ReadIntervalTimeout = MAXDWORD;
   1087   PortTimeOuts.ReadTotalTimeoutMultiplier = 0;
   1088   PortTimeOuts.ReadTotalTimeoutConstant = ConvertedTime;
   1089   PortTimeOuts.WriteTotalTimeoutMultiplier = ConvertedTime == 0 ? 1 : ConvertedTime;
   1090   PortTimeOuts.WriteTotalTimeoutConstant = 0;
   1091 
   1092   if (!Private->WinNtThunk->SetCommTimeouts (Private->NtHandle, &PortTimeOuts)) {
   1093     Private->NtError = Private->WinNtThunk->GetLastError ();
   1094     DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommTimeouts %d\n", Private->NtError));
   1095     gBS->RestoreTPL (Tpl);
   1096     return EFI_DEVICE_ERROR;
   1097   }
   1098 
   1099   //
   1100   //  Update mode
   1101   //
   1102   Private->SerialIoMode.BaudRate          = BaudRate;
   1103   Private->SerialIoMode.ReceiveFifoDepth  = ReceiveFifoDepth;
   1104   Private->SerialIoMode.Timeout           = Timeout;
   1105   Private->SerialIoMode.Parity            = Parity;
   1106   Private->SerialIoMode.DataBits          = DataBits;
   1107   Private->SerialIoMode.StopBits          = StopBits;
   1108 
   1109   //
   1110   // See if Device Path Node has actually changed
   1111   //
   1112   if (Private->UartDevicePath.BaudRate     == BaudRate &&
   1113       Private->UartDevicePath.DataBits     == DataBits &&
   1114       Private->UartDevicePath.Parity       == Parity   &&
   1115       Private->UartDevicePath.StopBits     == StopBits    ) {
   1116     gBS->RestoreTPL(Tpl);
   1117     return EFI_SUCCESS;
   1118   }
   1119 
   1120   //
   1121   // Update the device path
   1122   //
   1123   Private->UartDevicePath.BaudRate  = BaudRate;
   1124   Private->UartDevicePath.DataBits  = DataBits;
   1125   Private->UartDevicePath.Parity    = (UINT8) Parity;
   1126   Private->UartDevicePath.StopBits  = (UINT8) StopBits;
   1127 
   1128   Status = EFI_SUCCESS;
   1129   if (Private->Handle != NULL) {
   1130     Uart = (UART_DEVICE_PATH *) (
   1131              (UINTN) Private->DevicePath
   1132              + GetDevicePathSize (Private->ParentDevicePath)
   1133              - END_DEVICE_PATH_LENGTH
   1134              );
   1135     CopyMem (Uart, &Private->UartDevicePath, sizeof (UART_DEVICE_PATH));
   1136     Status = gBS->ReinstallProtocolInterface (
   1137                     Private->Handle,
   1138                     &gEfiDevicePathProtocolGuid,
   1139                     Private->DevicePath,
   1140                     Private->DevicePath
   1141                     );
   1142   }
   1143 
   1144   gBS->RestoreTPL (Tpl);
   1145 
   1146   return Status;
   1147 }
   1148 
   1149 EFI_STATUS
   1150 EFIAPI
   1151 WinNtSerialIoSetControl (
   1152   IN EFI_SERIAL_IO_PROTOCOL *This,
   1153   IN UINT32                 Control
   1154   )
   1155 /*++
   1156 
   1157 Routine Description:
   1158 
   1159   TODO: Add function description
   1160 
   1161 Arguments:
   1162 
   1163   This    - TODO: add argument description
   1164   Control - TODO: add argument description
   1165 
   1166 Returns:
   1167 
   1168   EFI_DEVICE_ERROR - TODO: Add description for return value
   1169   EFI_DEVICE_ERROR - TODO: Add description for return value
   1170   EFI_SUCCESS - TODO: Add description for return value
   1171 
   1172 --*/
   1173 {
   1174   WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
   1175   BOOL                          Result;
   1176   DCB                           Dcb;
   1177   EFI_TPL                       Tpl;
   1178   UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;
   1179   EFI_STATUS                    Status;
   1180 
   1181   //
   1182   // first determine the parameter is invalid
   1183   //
   1184   if (Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |
   1185                    EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |
   1186                    EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) {
   1187     return EFI_UNSUPPORTED;
   1188   }
   1189 
   1190   Tpl     = gBS->RaiseTPL (TPL_NOTIFY);
   1191 
   1192   Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
   1193 
   1194   Result  = Private->WinNtThunk->GetCommState (Private->NtHandle, &Dcb);
   1195 
   1196   if (!Result) {
   1197     Private->NtError = Private->WinNtThunk->GetLastError ();
   1198     DEBUG ((EFI_D_ERROR, "SerialSetControl: GetCommState %d\n", Private->NtError));
   1199     gBS->RestoreTPL (Tpl);
   1200     return EFI_DEVICE_ERROR;
   1201   }
   1202 
   1203   Dcb.fRtsControl                 = RTS_CONTROL_DISABLE;
   1204   Dcb.fDtrControl                 = DTR_CONTROL_DISABLE;
   1205   Private->HardwareFlowControl    = FALSE;
   1206   Private->SoftwareLoopbackEnable = FALSE;
   1207   Private->HardwareLoopbackEnable = FALSE;
   1208 
   1209   if (Control & EFI_SERIAL_REQUEST_TO_SEND) {
   1210     Dcb.fRtsControl = RTS_CONTROL_ENABLE;
   1211   }
   1212 
   1213   if (Control & EFI_SERIAL_DATA_TERMINAL_READY) {
   1214     Dcb.fDtrControl = DTR_CONTROL_ENABLE;
   1215   }
   1216 
   1217   if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
   1218     Private->HardwareFlowControl = TRUE;
   1219   }
   1220 
   1221   if (Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) {
   1222     Private->SoftwareLoopbackEnable = TRUE;
   1223   }
   1224 
   1225   if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
   1226     Private->HardwareLoopbackEnable = TRUE;
   1227   }
   1228 
   1229   Result = Private->WinNtThunk->SetCommState (
   1230                                   Private->NtHandle,
   1231                                   &Dcb
   1232                                   );
   1233 
   1234   if (!Result) {
   1235     Private->NtError = Private->WinNtThunk->GetLastError ();
   1236     DEBUG ((EFI_D_ERROR, "SerialSetControl: SetCommState %d\n", Private->NtError));
   1237     gBS->RestoreTPL (Tpl);
   1238     return EFI_DEVICE_ERROR;
   1239   }
   1240 
   1241   Status = EFI_SUCCESS;
   1242   if (Private->Handle != NULL) {
   1243     FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) (
   1244                     (UINTN) Private->DevicePath
   1245                     + GetDevicePathSize (Private->ParentDevicePath)
   1246                     - END_DEVICE_PATH_LENGTH
   1247                     + sizeof (UART_DEVICE_PATH)
   1248                     );
   1249     if (IsUartFlowControlNode (FlowControl) &&
   1250         ((FlowControl->FlowControlMap == UART_FLOW_CONTROL_HARDWARE) ^ Private->HardwareFlowControl)) {
   1251       //
   1252       // Flow Control setting is changed, need to reinstall device path protocol
   1253       //
   1254       FlowControl->FlowControlMap = Private->HardwareFlowControl ? UART_FLOW_CONTROL_HARDWARE : 0;
   1255       Status = gBS->ReinstallProtocolInterface (
   1256                       Private->Handle,
   1257                       &gEfiDevicePathProtocolGuid,
   1258                       Private->DevicePath,
   1259                       Private->DevicePath
   1260                       );
   1261     }
   1262   }
   1263 
   1264   gBS->RestoreTPL (Tpl);
   1265 
   1266   return Status;
   1267 }
   1268 
   1269 EFI_STATUS
   1270 EFIAPI
   1271 WinNtSerialIoGetControl (
   1272   IN  EFI_SERIAL_IO_PROTOCOL  *This,
   1273   OUT UINT32                  *Control
   1274   )
   1275 /*++
   1276 
   1277 Routine Description:
   1278 
   1279   TODO: Add function description
   1280 
   1281 Arguments:
   1282 
   1283   This    - TODO: add argument description
   1284   Control - TODO: add argument description
   1285 
   1286 Returns:
   1287 
   1288   EFI_DEVICE_ERROR - TODO: Add description for return value
   1289   EFI_DEVICE_ERROR - TODO: Add description for return value
   1290   EFI_DEVICE_ERROR - TODO: Add description for return value
   1291   EFI_SUCCESS - TODO: Add description for return value
   1292 
   1293 --*/
   1294 {
   1295   WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
   1296   DWORD                         ModemStatus;
   1297   DWORD                         Errors;
   1298   UINT32                        Bits;
   1299   DCB                           Dcb;
   1300   EFI_TPL                       Tpl;
   1301 
   1302   Tpl     = gBS->RaiseTPL (TPL_NOTIFY);
   1303 
   1304   Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
   1305 
   1306   //
   1307   //  Get modem status
   1308   //
   1309   if (!Private->WinNtThunk->GetCommModemStatus (Private->NtHandle, &ModemStatus)) {
   1310     Private->NtError = Private->WinNtThunk->GetLastError ();
   1311     gBS->RestoreTPL (Tpl);
   1312     return EFI_DEVICE_ERROR;
   1313   }
   1314 
   1315   Bits = 0;
   1316   if (ModemStatus & MS_CTS_ON) {
   1317     Bits |= EFI_SERIAL_CLEAR_TO_SEND;
   1318   }
   1319 
   1320   if (ModemStatus & MS_DSR_ON) {
   1321     Bits |= EFI_SERIAL_DATA_SET_READY;
   1322   }
   1323 
   1324   if (ModemStatus & MS_RING_ON) {
   1325     Bits |= EFI_SERIAL_RING_INDICATE;
   1326   }
   1327 
   1328   if (ModemStatus & MS_RLSD_ON) {
   1329     Bits |= EFI_SERIAL_CARRIER_DETECT;
   1330   }
   1331 
   1332   //
   1333   // Get ctrl status
   1334   //
   1335   if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Dcb)) {
   1336     Private->NtError = Private->WinNtThunk->GetLastError ();
   1337     DEBUG ((EFI_D_ERROR, "SerialGetControl: GetCommState %d\n", Private->NtError));
   1338     gBS->RestoreTPL (Tpl);
   1339     return EFI_DEVICE_ERROR;
   1340   }
   1341 
   1342   if (Dcb.fDtrControl == DTR_CONTROL_ENABLE) {
   1343     Bits |= EFI_SERIAL_DATA_TERMINAL_READY;
   1344   }
   1345 
   1346   if (Dcb.fRtsControl == RTS_CONTROL_ENABLE) {
   1347     Bits |= EFI_SERIAL_REQUEST_TO_SEND;
   1348   }
   1349 
   1350   if (Private->HardwareFlowControl) {
   1351     Bits |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
   1352   }
   1353 
   1354   if (Private->SoftwareLoopbackEnable) {
   1355     Bits |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
   1356   }
   1357 
   1358   if (Private->HardwareLoopbackEnable) {
   1359     Bits |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
   1360   }
   1361 
   1362   //
   1363   //  Get input buffer status
   1364   //
   1365   if (!Private->WinNtThunk->ClearCommError (Private->NtHandle, &Errors, &Private->NtComStatus)) {
   1366     Private->NtError = Private->WinNtThunk->GetLastError ();
   1367     DEBUG ((EFI_D_ERROR, "SerialGetControl: ClearCommError %d\n", Private->NtError));
   1368     gBS->RestoreTPL (Tpl);
   1369     return EFI_DEVICE_ERROR;
   1370   }
   1371 
   1372   if (Private->NtComStatus.cbInQue == 0) {
   1373     Bits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
   1374   }
   1375 
   1376   *Control = Bits;
   1377 
   1378   gBS->RestoreTPL (Tpl);
   1379 
   1380   return EFI_SUCCESS;
   1381 }
   1382 
   1383 EFI_STATUS
   1384 EFIAPI
   1385 WinNtSerialIoWrite (
   1386   IN EFI_SERIAL_IO_PROTOCOL   *This,
   1387   IN OUT UINTN                *BufferSize,
   1388   IN VOID                     *Buffer
   1389   )
   1390 /*++
   1391 
   1392 Routine Description:
   1393 
   1394   TODO: Add function description
   1395 
   1396 Arguments:
   1397 
   1398   This        - TODO: add argument description
   1399   BufferSize  - TODO: add argument description
   1400   Buffer      - TODO: add argument description
   1401 
   1402 Returns:
   1403 
   1404   EFI_DEVICE_ERROR - TODO: Add description for return value
   1405   EFI_SUCCESS - TODO: Add description for return value
   1406 
   1407 --*/
   1408 {
   1409   WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
   1410   UINT8                         *ByteBuffer;
   1411   UINTN                         TotalBytesWritten;
   1412   DWORD                         BytesToGo;
   1413   DWORD                         BytesWritten;
   1414   BOOL                          Result;
   1415   UINT32                        Index;
   1416   UINT32                        Control;
   1417   EFI_TPL                       Tpl;
   1418 
   1419   Tpl               = gBS->RaiseTPL (TPL_NOTIFY);
   1420 
   1421   Private           = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
   1422 
   1423   ByteBuffer        = (UINT8 *) Buffer;
   1424   TotalBytesWritten = 0;
   1425 
   1426   if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) {
   1427     for (Index = 0; Index < *BufferSize; Index++) {
   1428       if (IsaSerialFifoAdd (&Private->Fifo, ByteBuffer[Index]) == EFI_SUCCESS) {
   1429         TotalBytesWritten++;
   1430       } else {
   1431         break;
   1432       }
   1433     }
   1434   } else {
   1435     BytesToGo = (DWORD) (*BufferSize);
   1436 
   1437     do {
   1438       if (Private->HardwareFlowControl) {
   1439         //
   1440         // Send RTS
   1441         //
   1442         WinNtSerialIoGetControl (&Private->SerialIo, &Control);
   1443         Control |= EFI_SERIAL_REQUEST_TO_SEND;
   1444         WinNtSerialIoSetControl (&Private->SerialIo, Control);
   1445       }
   1446 
   1447       //
   1448       //  Do the write
   1449       //
   1450       Result = Private->WinNtThunk->WriteFile (
   1451                                       Private->NtHandle,
   1452                                       &ByteBuffer[TotalBytesWritten],
   1453                                       BytesToGo,
   1454                                       &BytesWritten,
   1455                                       NULL
   1456                                       );
   1457 
   1458       if (Private->HardwareFlowControl) {
   1459         //
   1460         // Assert RTS
   1461         //
   1462         WinNtSerialIoGetControl (&Private->SerialIo, &Control);
   1463         Control &= ~ (UINT32) EFI_SERIAL_REQUEST_TO_SEND;
   1464         WinNtSerialIoSetControl (&Private->SerialIo, Control);
   1465       }
   1466 
   1467       TotalBytesWritten += BytesWritten;
   1468       BytesToGo -= BytesWritten;
   1469       if (!Result) {
   1470         Private->NtError = Private->WinNtThunk->GetLastError ();
   1471         DEBUG ((EFI_D_ERROR, "SerialWrite: FileWrite %d\n", Private->NtError));
   1472         *BufferSize = TotalBytesWritten;
   1473         gBS->RestoreTPL (Tpl);
   1474         return EFI_DEVICE_ERROR;
   1475       }
   1476     } while (BytesToGo > 0);
   1477   }
   1478 
   1479   *BufferSize = TotalBytesWritten;
   1480 
   1481   gBS->RestoreTPL (Tpl);
   1482 
   1483   return EFI_SUCCESS;
   1484 }
   1485 
   1486 EFI_STATUS
   1487 EFIAPI
   1488 WinNtSerialIoRead (
   1489   IN  EFI_SERIAL_IO_PROTOCOL  *This,
   1490   IN  OUT UINTN               *BufferSize,
   1491   OUT VOID                    *Buffer
   1492   )
   1493 /*++
   1494 
   1495 Routine Description:
   1496 
   1497   TODO: Add function description
   1498 
   1499 Arguments:
   1500 
   1501   This        - TODO: add argument description
   1502   BufferSize  - TODO: add argument description
   1503   Buffer      - TODO: add argument description
   1504 
   1505 Returns:
   1506 
   1507   EFI_DEVICE_ERROR - TODO: Add description for return value
   1508 
   1509 --*/
   1510 {
   1511   WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
   1512   BOOL                          Result;
   1513   DWORD                         BytesRead;
   1514   EFI_STATUS                    Status;
   1515   UINT32                        Index;
   1516   UINT8                         Data;
   1517   UINT32                        Control;
   1518   EFI_TPL                       Tpl;
   1519 
   1520   Tpl     = gBS->RaiseTPL (TPL_NOTIFY);
   1521 
   1522   Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
   1523 
   1524   //
   1525   //  Do the read
   1526   //
   1527   if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) {
   1528     for (Index = 0, BytesRead = 0; Index < *BufferSize; Index++) {
   1529       if (IsaSerialFifoRemove (&Private->Fifo, &Data) == EFI_SUCCESS) {
   1530         ((UINT8 *) Buffer)[Index] = Data;
   1531         BytesRead++;
   1532       } else {
   1533         break;
   1534       }
   1535     }
   1536   } else {
   1537     if (Private->HardwareFlowControl) {
   1538       WinNtSerialIoGetControl (&Private->SerialIo, &Control);
   1539       Control |= EFI_SERIAL_DATA_TERMINAL_READY;
   1540       WinNtSerialIoSetControl (&Private->SerialIo, Control);
   1541     }
   1542 
   1543     Result = Private->WinNtThunk->ReadFile (
   1544                                     Private->NtHandle,
   1545                                     Buffer,
   1546                                     (DWORD) *BufferSize,
   1547                                     &BytesRead,
   1548                                     NULL
   1549                                     );
   1550 
   1551     if (Private->HardwareFlowControl) {
   1552       WinNtSerialIoGetControl (&Private->SerialIo, &Control);
   1553       Control &= ~ (UINT32) EFI_SERIAL_DATA_TERMINAL_READY;
   1554       WinNtSerialIoSetControl (&Private->SerialIo, Control);
   1555     }
   1556 
   1557     if (!Result) {
   1558       Private->NtError = Private->WinNtThunk->GetLastError ();
   1559       gBS->RestoreTPL (Tpl);
   1560       return EFI_DEVICE_ERROR;
   1561     }
   1562   }
   1563 
   1564   if (BytesRead != *BufferSize) {
   1565     Status = EFI_TIMEOUT;
   1566   } else {
   1567     Status = EFI_SUCCESS;
   1568   }
   1569 
   1570   *BufferSize = (UINTN) BytesRead;
   1571 
   1572   gBS->RestoreTPL (Tpl);
   1573 
   1574   return Status;
   1575 }
   1576 
   1577 BOOLEAN
   1578 IsaSerialFifoFull (
   1579   IN SERIAL_DEV_FIFO *Fifo
   1580   )
   1581 /*++
   1582 
   1583   Routine Description:
   1584   Detect whether specific FIFO is full or not
   1585 
   1586   Arguments:
   1587   Fifo  SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
   1588 
   1589   Returns:
   1590   TRUE:  the FIFO is full
   1591   FALSE: the FIFO is not full
   1592 
   1593 --*/
   1594 {
   1595   if (Fifo->Surplus == 0) {
   1596     return TRUE;
   1597   }
   1598 
   1599   return FALSE;
   1600 }
   1601 
   1602 BOOLEAN
   1603 IsaSerialFifoEmpty (
   1604   IN SERIAL_DEV_FIFO *Fifo
   1605   )
   1606 /*++
   1607 
   1608   Routine Description:
   1609   Detect whether specific FIFO is empty or not
   1610 
   1611   Arguments:
   1612     Fifo  SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
   1613 
   1614   Returns:
   1615     TRUE:  the FIFO is empty
   1616     FALSE: the FIFO is not empty
   1617 
   1618 --*/
   1619 {
   1620   if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) {
   1621     return TRUE;
   1622   }
   1623 
   1624   return FALSE;
   1625 }
   1626 
   1627 EFI_STATUS
   1628 IsaSerialFifoAdd (
   1629   IN SERIAL_DEV_FIFO *Fifo,
   1630   IN UINT8           Data
   1631   )
   1632 /*++
   1633 
   1634   Routine Description:
   1635   Add data to specific FIFO
   1636 
   1637   Arguments:
   1638     Fifo  SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
   1639     Data  UINT8: the data added to FIFO
   1640 
   1641   Returns:
   1642     EFI_SUCCESS:  Add data to specific FIFO successfully
   1643     EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
   1644 
   1645 --*/
   1646 // TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment
   1647 {
   1648   //
   1649   // if FIFO full can not add data
   1650   //
   1651   if (IsaSerialFifoFull (Fifo)) {
   1652     return EFI_OUT_OF_RESOURCES;
   1653   }
   1654 
   1655   //
   1656   // FIFO is not full can add data
   1657   //
   1658   Fifo->Data[Fifo->Last] = Data;
   1659   Fifo->Surplus--;
   1660   Fifo->Last++;
   1661   if (Fifo->Last >= SERIAL_MAX_BUFFER_SIZE) {
   1662     Fifo->Last = 0;
   1663   }
   1664 
   1665   return EFI_SUCCESS;
   1666 }
   1667 
   1668 EFI_STATUS
   1669 IsaSerialFifoRemove (
   1670   IN  SERIAL_DEV_FIFO *Fifo,
   1671   OUT UINT8           *Data
   1672   )
   1673 /*++
   1674 
   1675   Routine Description:
   1676   Remove data from specific FIFO
   1677 
   1678   Arguments:
   1679     Fifo  SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
   1680     Data  UINT8*: the data removed from FIFO
   1681 
   1682   Returns:
   1683     EFI_SUCCESS:  Remove data from specific FIFO successfully
   1684     EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
   1685 
   1686 --*/
   1687 // TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment
   1688 {
   1689   //
   1690   // if FIFO is empty, no data can remove
   1691   //
   1692   if (IsaSerialFifoEmpty (Fifo)) {
   1693     return EFI_OUT_OF_RESOURCES;
   1694   }
   1695 
   1696   //
   1697   // FIFO is not empty, can remove data
   1698   //
   1699   *Data = Fifo->Data[Fifo->First];
   1700   Fifo->Surplus++;
   1701   Fifo->First++;
   1702   if (Fifo->First >= SERIAL_MAX_BUFFER_SIZE) {
   1703     Fifo->First = 0;
   1704   }
   1705 
   1706   return EFI_SUCCESS;
   1707 }
   1708