Home | History | Annotate | Download | only in SerialDxe
      1 /** @file
      2   Serial driver that layers on top of a Serial Port Library instance.
      3 
      4   Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
      5   Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>
      6   Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
      7 
      8   This program and the accompanying materials
      9   are licensed and made available under the terms and conditions of the BSD License
     10   which accompanies this distribution.  The full text of the license may be found at
     11   http://opensource.org/licenses/bsd-license.php
     12 
     13   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     14   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     15 
     16 **/
     17 
     18 #include <Library/UefiBootServicesTableLib.h>
     19 #include <Library/SerialPortLib.h>
     20 #include <Library/DebugLib.h>
     21 #include <Library/PcdLib.h>
     22 
     23 #include <Protocol/SerialIo.h>
     24 #include <Protocol/DevicePath.h>
     25 
     26 typedef struct {
     27   VENDOR_DEVICE_PATH        Guid;
     28   UART_DEVICE_PATH          Uart;
     29   EFI_DEVICE_PATH_PROTOCOL  End;
     30 } SERIAL_DEVICE_PATH;
     31 
     32 /**
     33   Reset the serial device.
     34 
     35   @param  This              Protocol instance pointer.
     36 
     37   @retval EFI_SUCCESS       The device was reset.
     38   @retval EFI_DEVICE_ERROR  The serial device could not be reset.
     39 
     40 **/
     41 EFI_STATUS
     42 EFIAPI
     43 SerialReset (
     44   IN EFI_SERIAL_IO_PROTOCOL *This
     45   );
     46 
     47 /**
     48   Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
     49   data bits, and stop bits on a serial device.
     50 
     51   @param  This             Protocol instance pointer.
     52   @param  BaudRate         The requested baud rate. A BaudRate value of 0 will use the the
     53                            device's default interface speed.
     54   @param  ReceiveFifoDepth The requested depth of the FIFO on the receive side of the
     55                            serial interface. A ReceiveFifoDepth value of 0 will use
     56                            the device's default FIFO depth.
     57   @param  Timeout          The requested time out for a single character in microseconds.
     58                            This timeout applies to both the transmit and receive side of the
     59                            interface. A Timeout value of 0 will use the device's default time
     60                            out value.
     61   @param  Parity           The type of parity to use on this serial device. A Parity value of
     62                            DefaultParity will use the device's default parity value.
     63   @param  DataBits         The number of data bits to use on the serial device. A DataBits
     64                            value of 0 will use the device's default data bit setting.
     65   @param  StopBits         The number of stop bits to use on this serial device. A StopBits
     66                            value of DefaultStopBits will use the device's default number of
     67                            stop bits.
     68 
     69   @retval EFI_SUCCESS      The device was reset.
     70   @retval EFI_DEVICE_ERROR The serial device could not be reset.
     71 
     72 **/
     73 EFI_STATUS
     74 EFIAPI
     75 SerialSetAttributes (
     76   IN EFI_SERIAL_IO_PROTOCOL *This,
     77   IN UINT64                 BaudRate,
     78   IN UINT32                 ReceiveFifoDepth,
     79   IN UINT32                 Timeout,
     80   IN EFI_PARITY_TYPE        Parity,
     81   IN UINT8                  DataBits,
     82   IN EFI_STOP_BITS_TYPE     StopBits
     83   );
     84 
     85 /**
     86   Set the control bits on a serial device
     87 
     88   @param  This             Protocol instance pointer.
     89   @param  Control          Set the bits of Control that are settable.
     90 
     91   @retval EFI_SUCCESS      The new control bits were set on the serial device.
     92   @retval EFI_UNSUPPORTED  The serial device does not support this operation.
     93   @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
     94 
     95 **/
     96 EFI_STATUS
     97 EFIAPI
     98 SerialSetControl (
     99   IN EFI_SERIAL_IO_PROTOCOL *This,
    100   IN UINT32                 Control
    101   );
    102 
    103 /**
    104   Retrieves the status of the control bits on a serial device
    105 
    106   @param  This              Protocol instance pointer.
    107   @param  Control           A pointer to return the current Control signals from the serial device.
    108 
    109   @retval EFI_SUCCESS       The control bits were read from the serial device.
    110   @retval EFI_DEVICE_ERROR  The serial device is not functioning correctly.
    111 
    112 **/
    113 EFI_STATUS
    114 EFIAPI
    115 SerialGetControl (
    116   IN EFI_SERIAL_IO_PROTOCOL *This,
    117   OUT UINT32                *Control
    118   );
    119 
    120 /**
    121   Writes data to a serial device.
    122 
    123   @param  This              Protocol instance pointer.
    124   @param  BufferSize        On input, the size of the Buffer. On output, the amount of
    125                             data actually written.
    126   @param  Buffer            The buffer of data to write
    127 
    128   @retval EFI_SUCCESS       The data was written.
    129   @retval EFI_DEVICE_ERROR  The device reported an error.
    130   @retval EFI_TIMEOUT       The data write was stopped due to a timeout.
    131 
    132 **/
    133 EFI_STATUS
    134 EFIAPI
    135 SerialWrite (
    136   IN EFI_SERIAL_IO_PROTOCOL *This,
    137   IN OUT UINTN              *BufferSize,
    138   IN VOID                   *Buffer
    139   );
    140 
    141 /**
    142   Reads data from a serial device.
    143 
    144   @param  This              Protocol instance pointer.
    145   @param  BufferSize        On input, the size of the Buffer. On output, the amount of
    146                             data returned in Buffer.
    147   @param  Buffer            The buffer to return the data into.
    148 
    149   @retval EFI_SUCCESS       The data was read.
    150   @retval EFI_DEVICE_ERROR  The device reported an error.
    151   @retval EFI_TIMEOUT       The data write was stopped due to a timeout.
    152 
    153 **/
    154 EFI_STATUS
    155 EFIAPI
    156 SerialRead (
    157   IN EFI_SERIAL_IO_PROTOCOL *This,
    158   IN OUT UINTN              *BufferSize,
    159   OUT VOID                  *Buffer
    160   );
    161 
    162 EFI_HANDLE mSerialHandle = NULL;
    163 
    164 SERIAL_DEVICE_PATH mSerialDevicePath = {
    165   {
    166     { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH), 0} },
    167     EFI_CALLER_ID_GUID  // Use the driver's GUID
    168   },
    169   {
    170     { MESSAGING_DEVICE_PATH, MSG_UART_DP, { sizeof (UART_DEVICE_PATH), 0} },
    171     0,                  // Reserved
    172     0,                  // BaudRate
    173     0,                  // DataBits
    174     0,                  // Parity
    175     0                   // StopBits
    176   },
    177   { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } }
    178 };
    179 
    180 //
    181 // Template used to initialize the Serial IO protocols.
    182 //
    183 EFI_SERIAL_IO_MODE mSerialIoMode = {
    184   0, // ControlMask
    185   0, // Timeout
    186   0, // BaudRate
    187   1, // ReceiveFifoDepth
    188   0, // DataBits
    189   0, // Parity
    190   0  // StopBits
    191 };
    192 
    193 EFI_SERIAL_IO_PROTOCOL mSerialIoTemplate = {
    194   SERIAL_IO_INTERFACE_REVISION,
    195   SerialReset,
    196   SerialSetAttributes,
    197   SerialSetControl,
    198   SerialGetControl,
    199   SerialWrite,
    200   SerialRead,
    201   &mSerialIoMode
    202 };
    203 
    204 /**
    205   Reset the serial device.
    206 
    207   @param  This              Protocol instance pointer.
    208 
    209   @retval EFI_SUCCESS       The device was reset.
    210   @retval EFI_DEVICE_ERROR  The serial device could not be reset.
    211 
    212 **/
    213 EFI_STATUS
    214 EFIAPI
    215 SerialReset (
    216   IN EFI_SERIAL_IO_PROTOCOL *This
    217   )
    218 {
    219   EFI_STATUS    Status;
    220   EFI_TPL       Tpl;
    221 
    222   Status = SerialPortInitialize ();
    223   if (EFI_ERROR (Status)) {
    224     return Status;
    225   }
    226 
    227   //
    228   // Set the Serial I/O mode and update the device path
    229   //
    230 
    231   Tpl = gBS->RaiseTPL (TPL_NOTIFY);
    232 
    233   //
    234   // Set the Serial I/O mode
    235   //
    236   This->Mode->ReceiveFifoDepth  = 1;
    237   This->Mode->Timeout           = 0;
    238   This->Mode->BaudRate          = PcdGet64 (PcdUartDefaultBaudRate);
    239   This->Mode->DataBits          = (UINT32) PcdGet8 (PcdUartDefaultDataBits);
    240   This->Mode->Parity            = (UINT32) PcdGet8 (PcdUartDefaultParity);
    241   This->Mode->StopBits          = (UINT32) PcdGet8 (PcdUartDefaultStopBits);
    242 
    243   //
    244   // Check if the device path has actually changed
    245   //
    246   if (mSerialDevicePath.Uart.BaudRate == This->Mode->BaudRate &&
    247       mSerialDevicePath.Uart.DataBits == (UINT8) This->Mode->DataBits &&
    248       mSerialDevicePath.Uart.Parity   == (UINT8) This->Mode->Parity &&
    249       mSerialDevicePath.Uart.StopBits == (UINT8) This->Mode->StopBits
    250      ) {
    251     gBS->RestoreTPL (Tpl);
    252     return EFI_SUCCESS;
    253   }
    254 
    255   //
    256   // Update the device path
    257   //
    258   mSerialDevicePath.Uart.BaudRate = This->Mode->BaudRate;
    259   mSerialDevicePath.Uart.DataBits = (UINT8) This->Mode->DataBits;
    260   mSerialDevicePath.Uart.Parity   = (UINT8) This->Mode->Parity;
    261   mSerialDevicePath.Uart.StopBits = (UINT8) This->Mode->StopBits;
    262 
    263   Status = gBS->ReinstallProtocolInterface (
    264                   mSerialHandle,
    265                   &gEfiDevicePathProtocolGuid,
    266                   &mSerialDevicePath,
    267                   &mSerialDevicePath
    268                   );
    269 
    270   gBS->RestoreTPL (Tpl);
    271 
    272   return Status;
    273 }
    274 
    275 /**
    276   Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
    277   data bits, and stop bits on a serial device.
    278 
    279   @param  This             Protocol instance pointer.
    280   @param  BaudRate         The requested baud rate. A BaudRate value of 0 will use the the
    281                            device's default interface speed.
    282   @param  ReceiveFifoDepth The requested depth of the FIFO on the receive side of the
    283                            serial interface. A ReceiveFifoDepth value of 0 will use
    284                            the device's default FIFO depth.
    285   @param  Timeout          The requested time out for a single character in microseconds.
    286                            This timeout applies to both the transmit and receive side of the
    287                            interface. A Timeout value of 0 will use the device's default time
    288                            out value.
    289   @param  Parity           The type of parity to use on this serial device. A Parity value of
    290                            DefaultParity will use the device's default parity value.
    291   @param  DataBits         The number of data bits to use on the serial device. A DataBits
    292                            value of 0 will use the device's default data bit setting.
    293   @param  StopBits         The number of stop bits to use on this serial device. A StopBits
    294                            value of DefaultStopBits will use the device's default number of
    295                            stop bits.
    296 
    297   @retval EFI_SUCCESS      The device was reset.
    298   @retval EFI_DEVICE_ERROR The serial device could not be reset.
    299 
    300 **/
    301 EFI_STATUS
    302 EFIAPI
    303 SerialSetAttributes (
    304   IN EFI_SERIAL_IO_PROTOCOL *This,
    305   IN UINT64                 BaudRate,
    306   IN UINT32                 ReceiveFifoDepth,
    307   IN UINT32                 Timeout,
    308   IN EFI_PARITY_TYPE        Parity,
    309   IN UINT8                  DataBits,
    310   IN EFI_STOP_BITS_TYPE     StopBits
    311   )
    312 {
    313   EFI_STATUS    Status;
    314   EFI_TPL       Tpl;
    315 
    316   Status = SerialPortSetAttributes (&BaudRate, &ReceiveFifoDepth, &Timeout, &Parity, &DataBits, &StopBits);
    317   if (EFI_ERROR (Status)) {
    318     return Status;
    319   }
    320 
    321   //
    322   // Set the Serial I/O mode and update the device path
    323   //
    324 
    325   Tpl = gBS->RaiseTPL (TPL_NOTIFY);
    326 
    327   //
    328   // Set the Serial I/O mode
    329   //
    330   This->Mode->ReceiveFifoDepth  = ReceiveFifoDepth;
    331   This->Mode->Timeout           = Timeout;
    332   This->Mode->BaudRate          = BaudRate;
    333   This->Mode->DataBits          = (UINT32) DataBits;
    334   This->Mode->Parity            = (UINT32) Parity;
    335   This->Mode->StopBits          = (UINT32) StopBits;
    336 
    337   //
    338   // Check if the device path has actually changed
    339   //
    340   if (mSerialDevicePath.Uart.BaudRate == BaudRate &&
    341       mSerialDevicePath.Uart.DataBits == DataBits &&
    342       mSerialDevicePath.Uart.Parity   == (UINT8) Parity &&
    343       mSerialDevicePath.Uart.StopBits == (UINT8) StopBits
    344      ) {
    345     gBS->RestoreTPL (Tpl);
    346     return EFI_SUCCESS;
    347   }
    348 
    349   //
    350   // Update the device path
    351   //
    352   mSerialDevicePath.Uart.BaudRate = BaudRate;
    353   mSerialDevicePath.Uart.DataBits = DataBits;
    354   mSerialDevicePath.Uart.Parity   = (UINT8) Parity;
    355   mSerialDevicePath.Uart.StopBits = (UINT8) StopBits;
    356 
    357   Status = gBS->ReinstallProtocolInterface (
    358                   mSerialHandle,
    359                   &gEfiDevicePathProtocolGuid,
    360                   &mSerialDevicePath,
    361                   &mSerialDevicePath
    362                   );
    363 
    364   gBS->RestoreTPL (Tpl);
    365 
    366   return Status;
    367 }
    368 
    369 /**
    370   Set the control bits on a serial device
    371 
    372   @param  This             Protocol instance pointer.
    373   @param  Control          Set the bits of Control that are settable.
    374 
    375   @retval EFI_SUCCESS      The new control bits were set on the serial device.
    376   @retval EFI_UNSUPPORTED  The serial device does not support this operation.
    377   @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
    378 
    379 **/
    380 EFI_STATUS
    381 EFIAPI
    382 SerialSetControl (
    383   IN EFI_SERIAL_IO_PROTOCOL *This,
    384   IN UINT32                 Control
    385   )
    386 {
    387   return SerialPortSetControl (Control);
    388 }
    389 
    390 /**
    391   Retrieves the status of the control bits on a serial device
    392 
    393   @param  This              Protocol instance pointer.
    394   @param  Control           A pointer to return the current Control signals from the serial device.
    395 
    396   @retval EFI_SUCCESS       The control bits were read from the serial device.
    397   @retval EFI_DEVICE_ERROR  The serial device is not functioning correctly.
    398 
    399 **/
    400 EFI_STATUS
    401 EFIAPI
    402 SerialGetControl (
    403   IN EFI_SERIAL_IO_PROTOCOL *This,
    404   OUT UINT32                *Control
    405   )
    406 {
    407   return SerialPortGetControl (Control);
    408 }
    409 
    410 /**
    411   Writes data to a serial device.
    412 
    413   @param  This              Protocol instance pointer.
    414   @param  BufferSize        On input, the size of the Buffer. On output, the amount of
    415                             data actually written.
    416   @param  Buffer            The buffer of data to write
    417 
    418   @retval EFI_SUCCESS       The data was written.
    419   @retval EFI_DEVICE_ERROR  The device reported an error.
    420   @retval EFI_TIMEOUT       The data write was stopped due to a timeout.
    421 
    422 **/
    423 EFI_STATUS
    424 EFIAPI
    425 SerialWrite (
    426   IN EFI_SERIAL_IO_PROTOCOL *This,
    427   IN OUT UINTN              *BufferSize,
    428   IN VOID                   *Buffer
    429   )
    430 {
    431   UINTN Count;
    432 
    433   Count = SerialPortWrite (Buffer, *BufferSize);
    434 
    435   if (Count != *BufferSize) {
    436     *BufferSize = Count;
    437     return EFI_TIMEOUT;
    438   }
    439 
    440   return EFI_SUCCESS;
    441 }
    442 
    443 /**
    444   Reads data from a serial device.
    445 
    446   @param  This              Protocol instance pointer.
    447   @param  BufferSize        On input, the size of the Buffer. On output, the amount of
    448                             data returned in Buffer.
    449   @param  Buffer            The buffer to return the data into.
    450 
    451   @retval EFI_SUCCESS       The data was read.
    452   @retval EFI_DEVICE_ERROR  The device reported an error.
    453   @retval EFI_TIMEOUT       The data write was stopped due to a timeout.
    454 
    455 **/
    456 EFI_STATUS
    457 EFIAPI
    458 SerialRead (
    459   IN EFI_SERIAL_IO_PROTOCOL *This,
    460   IN OUT UINTN              *BufferSize,
    461   OUT VOID                  *Buffer
    462   )
    463 {
    464   UINTN Count;
    465 
    466   Count = 0;
    467 
    468   if (SerialPortPoll ()) {
    469     Count = SerialPortRead (Buffer, *BufferSize);
    470   }
    471 
    472   if (Count != *BufferSize) {
    473     *BufferSize = Count;
    474     return EFI_TIMEOUT;
    475   }
    476 
    477   return EFI_SUCCESS;
    478 }
    479 
    480 /**
    481   Initialization for the Serial Io Protocol.
    482 
    483   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
    484   @param[in] SystemTable    A pointer to the EFI System Table.
    485 
    486   @retval EFI_SUCCESS       The entry point is executed successfully.
    487   @retval other             Some error occurs when executing this entry point.
    488 
    489 **/
    490 EFI_STATUS
    491 EFIAPI
    492 SerialDxeInitialize (
    493   IN EFI_HANDLE         ImageHandle,
    494   IN EFI_SYSTEM_TABLE   *SystemTable
    495   )
    496 {
    497   EFI_STATUS            Status;
    498 
    499   Status = SerialPortInitialize ();
    500   if (EFI_ERROR (Status)) {
    501     return Status;
    502   }
    503 
    504   mSerialIoMode.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
    505   mSerialIoMode.DataBits = (UINT32) PcdGet8 (PcdUartDefaultDataBits);
    506   mSerialIoMode.Parity   = (UINT32) PcdGet8 (PcdUartDefaultParity);
    507   mSerialIoMode.StopBits = (UINT32) PcdGet8 (PcdUartDefaultStopBits);
    508   mSerialDevicePath.Uart.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
    509   mSerialDevicePath.Uart.DataBits = PcdGet8 (PcdUartDefaultDataBits);
    510   mSerialDevicePath.Uart.Parity   = PcdGet8 (PcdUartDefaultParity);
    511   mSerialDevicePath.Uart.StopBits = PcdGet8 (PcdUartDefaultStopBits);
    512 
    513   //
    514   // Make a new handle with Serial IO protocol and its device path on it.
    515   //
    516   Status = gBS->InstallMultipleProtocolInterfaces (
    517                   &mSerialHandle,
    518                   &gEfiSerialIoProtocolGuid,   &mSerialIoTemplate,
    519                   &gEfiDevicePathProtocolGuid, &mSerialDevicePath,
    520                   NULL
    521                   );
    522   ASSERT_EFI_ERROR (Status);
    523 
    524   return Status;
    525 }
    526 
    527