2 Serial driver that layers on top of a Serial Port Library instance.
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>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <Library/UefiBootServicesTableLib.h>
13 #include <Library/SerialPortLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/PcdLib.h>
17 #include <Protocol/SerialIo.h>
18 #include <Protocol/DevicePath.h>
19 #include <Guid/SerialPortLibVendor.h>
22 VENDOR_DEVICE_PATH Guid
;
23 UART_DEVICE_PATH Uart
;
24 EFI_DEVICE_PATH_PROTOCOL End
;
28 Reset the serial device.
30 @param This Protocol instance pointer.
32 @retval EFI_SUCCESS The device was reset.
33 @retval EFI_DEVICE_ERROR The serial device could not be reset.
39 IN EFI_SERIAL_IO_PROTOCOL
*This
43 Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
44 data bits, and stop bits on a serial device.
46 @param This Protocol instance pointer.
47 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
48 device's default interface speed.
49 @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the
50 serial interface. A ReceiveFifoDepth value of 0 will use
51 the device's default FIFO depth.
52 @param Timeout The requested time out for a single character in microseconds.
53 This timeout applies to both the transmit and receive side of the
54 interface. A Timeout value of 0 will use the device's default time
56 @param Parity The type of parity to use on this serial device. A Parity value of
57 DefaultParity will use the device's default parity value.
58 @param DataBits The number of data bits to use on the serial device. A DataBits
59 value of 0 will use the device's default data bit setting.
60 @param StopBits The number of stop bits to use on this serial device. A StopBits
61 value of DefaultStopBits will use the device's default number of
64 @retval EFI_SUCCESS The device was reset.
65 @retval EFI_INVALID_PARAMETER One or more attributes has an unsupported value.
66 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
72 IN EFI_SERIAL_IO_PROTOCOL
*This
,
74 IN UINT32 ReceiveFifoDepth
,
76 IN EFI_PARITY_TYPE Parity
,
78 IN EFI_STOP_BITS_TYPE StopBits
82 Set the control bits on a serial device
84 @param This Protocol instance pointer.
85 @param Control Set the bits of Control that are settable.
87 @retval EFI_SUCCESS The new control bits were set on the serial device.
88 @retval EFI_UNSUPPORTED The serial device does not support this operation.
89 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
95 IN EFI_SERIAL_IO_PROTOCOL
*This
,
100 Retrieves the status of the control bits on a serial device
102 @param This Protocol instance pointer.
103 @param Control A pointer to return the current Control signals from the serial device.
105 @retval EFI_SUCCESS The control bits were read from the serial device.
106 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
112 IN EFI_SERIAL_IO_PROTOCOL
*This
,
117 Writes data to a serial device.
119 @param This Protocol instance pointer.
120 @param BufferSize On input, the size of the Buffer. On output, the amount of
121 data actually written.
122 @param Buffer The buffer of data to write
124 @retval EFI_SUCCESS The data was written.
125 @retval EFI_DEVICE_ERROR The device reported an error.
126 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
132 IN EFI_SERIAL_IO_PROTOCOL
*This
,
133 IN OUT UINTN
*BufferSize
,
138 Reads data from a serial device.
140 @param This Protocol instance pointer.
141 @param BufferSize On input, the size of the Buffer. On output, the amount of
142 data returned in Buffer.
143 @param Buffer The buffer to return the data into.
145 @retval EFI_SUCCESS The data was read.
146 @retval EFI_DEVICE_ERROR The device reported an error.
147 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
153 IN EFI_SERIAL_IO_PROTOCOL
*This
,
154 IN OUT UINTN
*BufferSize
,
158 EFI_HANDLE mSerialHandle
= NULL
;
160 SERIAL_DEVICE_PATH mSerialDevicePath
= {
162 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, { sizeof (VENDOR_DEVICE_PATH
), 0} },
163 EDKII_SERIAL_PORT_LIB_VENDOR_GUID
166 { MESSAGING_DEVICE_PATH
, MSG_UART_DP
, { sizeof (UART_DEVICE_PATH
), 0} },
173 { END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
, { sizeof (EFI_DEVICE_PATH_PROTOCOL
), 0 } }
177 // Template used to initialize the Serial IO protocols.
179 EFI_SERIAL_IO_MODE mSerialIoMode
= {
181 // value field set in SerialDxeInitialize()?
182 //--------- ------------------- -----------------------------
184 1000 * 1000, // Timeout
186 1, // ReceiveFifoDepth
192 EFI_SERIAL_IO_PROTOCOL mSerialIoTemplate
= {
193 SERIAL_IO_INTERFACE_REVISION
,
204 Reset the serial device.
206 @param This Protocol instance pointer.
208 @retval EFI_SUCCESS The device was reset.
209 @retval EFI_DEVICE_ERROR The serial device could not be reset.
215 IN EFI_SERIAL_IO_PROTOCOL
*This
220 Status
= SerialPortInitialize ();
221 if (EFI_ERROR (Status
)) {
226 // Go set the current attributes
228 Status
= This
->SetAttributes (
230 This
->Mode
->BaudRate
,
231 This
->Mode
->ReceiveFifoDepth
,
233 (EFI_PARITY_TYPE
) This
->Mode
->Parity
,
234 (UINT8
) This
->Mode
->DataBits
,
235 (EFI_STOP_BITS_TYPE
) This
->Mode
->StopBits
239 // The serial device may not support some of the attributes. To prevent
240 // later failure, always return EFI_SUCCESS when SetAttributes is returning
241 // EFI_INVALID_PARAMETER.
243 if (Status
== EFI_INVALID_PARAMETER
) {
251 Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
252 data bits, and stop bits on a serial device.
254 @param This Protocol instance pointer.
255 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
256 device's default interface speed.
257 @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the
258 serial interface. A ReceiveFifoDepth value of 0 will use
259 the device's default FIFO depth.
260 @param Timeout The requested time out for a single character in microseconds.
261 This timeout applies to both the transmit and receive side of the
262 interface. A Timeout value of 0 will use the device's default time
264 @param Parity The type of parity to use on this serial device. A Parity value of
265 DefaultParity will use the device's default parity value.
266 @param DataBits The number of data bits to use on the serial device. A DataBits
267 value of 0 will use the device's default data bit setting.
268 @param StopBits The number of stop bits to use on this serial device. A StopBits
269 value of DefaultStopBits will use the device's default number of
272 @retval EFI_SUCCESS The device was reset.
273 @retval EFI_INVALID_PARAMETER One or more attributes has an unsupported value.
274 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
279 SerialSetAttributes (
280 IN EFI_SERIAL_IO_PROTOCOL
*This
,
282 IN UINT32 ReceiveFifoDepth
,
284 IN EFI_PARITY_TYPE Parity
,
286 IN EFI_STOP_BITS_TYPE StopBits
291 UINT64 OriginalBaudRate
;
292 UINT32 OriginalReceiveFifoDepth
;
293 UINT32 OriginalTimeout
;
294 EFI_PARITY_TYPE OriginalParity
;
295 UINT8 OriginalDataBits
;
296 EFI_STOP_BITS_TYPE OriginalStopBits
;
299 // Preserve the original input values in case
300 // SerialPortSetAttributes() updates the input/output
301 // parameters even on error.
303 OriginalBaudRate
= BaudRate
;
304 OriginalReceiveFifoDepth
= ReceiveFifoDepth
;
305 OriginalTimeout
= Timeout
;
306 OriginalParity
= Parity
;
307 OriginalDataBits
= DataBits
;
308 OriginalStopBits
= StopBits
;
309 Status
= SerialPortSetAttributes (&BaudRate
, &ReceiveFifoDepth
, &Timeout
, &Parity
, &DataBits
, &StopBits
);
310 if (EFI_ERROR (Status
)) {
312 // If it is just to set Timeout value and unsupported is returned,
313 // do not return error.
315 if ((Status
== EFI_UNSUPPORTED
) &&
316 (This
->Mode
->Timeout
!= OriginalTimeout
) &&
317 (This
->Mode
->ReceiveFifoDepth
== OriginalReceiveFifoDepth
) &&
318 (This
->Mode
->BaudRate
== OriginalBaudRate
) &&
319 (This
->Mode
->DataBits
== (UINT32
) OriginalDataBits
) &&
320 (This
->Mode
->Parity
== (UINT32
) OriginalParity
) &&
321 (This
->Mode
->StopBits
== (UINT32
) OriginalStopBits
)) {
323 // Restore to the original input values.
325 BaudRate
= OriginalBaudRate
;
326 ReceiveFifoDepth
= OriginalReceiveFifoDepth
;
327 Timeout
= OriginalTimeout
;
328 Parity
= OriginalParity
;
329 DataBits
= OriginalDataBits
;
330 StopBits
= OriginalStopBits
;
331 Status
= EFI_SUCCESS
;
332 } else if (Status
== EFI_INVALID_PARAMETER
|| Status
== EFI_UNSUPPORTED
) {
333 return EFI_INVALID_PARAMETER
;
335 return EFI_DEVICE_ERROR
;
340 // Set the Serial I/O mode and update the device path
343 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
346 // Set the Serial I/O mode
348 This
->Mode
->ReceiveFifoDepth
= ReceiveFifoDepth
;
349 This
->Mode
->Timeout
= Timeout
;
350 This
->Mode
->BaudRate
= BaudRate
;
351 This
->Mode
->DataBits
= (UINT32
) DataBits
;
352 This
->Mode
->Parity
= (UINT32
) Parity
;
353 This
->Mode
->StopBits
= (UINT32
) StopBits
;
356 // Check if the device path has actually changed
358 if (mSerialDevicePath
.Uart
.BaudRate
== BaudRate
&&
359 mSerialDevicePath
.Uart
.DataBits
== DataBits
&&
360 mSerialDevicePath
.Uart
.Parity
== (UINT8
) Parity
&&
361 mSerialDevicePath
.Uart
.StopBits
== (UINT8
) StopBits
363 gBS
->RestoreTPL (Tpl
);
368 // Update the device path
370 mSerialDevicePath
.Uart
.BaudRate
= BaudRate
;
371 mSerialDevicePath
.Uart
.DataBits
= DataBits
;
372 mSerialDevicePath
.Uart
.Parity
= (UINT8
) Parity
;
373 mSerialDevicePath
.Uart
.StopBits
= (UINT8
) StopBits
;
375 Status
= gBS
->ReinstallProtocolInterface (
377 &gEfiDevicePathProtocolGuid
,
382 gBS
->RestoreTPL (Tpl
);
388 Set the control bits on a serial device
390 @param This Protocol instance pointer.
391 @param Control Set the bits of Control that are settable.
393 @retval EFI_SUCCESS The new control bits were set on the serial device.
394 @retval EFI_UNSUPPORTED The serial device does not support this operation.
395 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
401 IN EFI_SERIAL_IO_PROTOCOL
*This
,
405 return SerialPortSetControl (Control
);
409 Retrieves the status of the control bits on a serial device
411 @param This Protocol instance pointer.
412 @param Control A pointer to return the current Control signals from the serial device.
414 @retval EFI_SUCCESS The control bits were read from the serial device.
415 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
421 IN EFI_SERIAL_IO_PROTOCOL
*This
,
425 return SerialPortGetControl (Control
);
429 Writes data to a serial device.
431 @param This Protocol instance pointer.
432 @param BufferSize On input, the size of the Buffer. On output, the amount of
433 data actually written.
434 @param Buffer The buffer of data to write
436 @retval EFI_SUCCESS The data was written.
437 @retval EFI_DEVICE_ERROR The device reported an error.
438 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
444 IN EFI_SERIAL_IO_PROTOCOL
*This
,
445 IN OUT UINTN
*BufferSize
,
451 Count
= SerialPortWrite (Buffer
, *BufferSize
);
453 if (Count
!= *BufferSize
) {
462 Reads data from a serial device.
464 @param This Protocol instance pointer.
465 @param BufferSize On input, the size of the Buffer. On output, the amount of
466 data returned in Buffer.
467 @param Buffer The buffer to return the data into.
469 @retval EFI_SUCCESS The data was read.
470 @retval EFI_DEVICE_ERROR The device reported an error.
471 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
477 IN EFI_SERIAL_IO_PROTOCOL
*This
,
478 IN OUT UINTN
*BufferSize
,
487 while (Count
< *BufferSize
) {
489 while (TimeOut
< mSerialIoMode
.Timeout
) {
490 if (SerialPortPoll ()) {
496 if (TimeOut
>= mSerialIoMode
.Timeout
) {
499 SerialPortRead (Buffer
, 1);
501 Buffer
= (VOID
*) ((UINT8
*) Buffer
+ 1);
504 if (Count
!= *BufferSize
) {
513 Initialization for the Serial Io Protocol.
515 @param[in] ImageHandle The firmware allocated handle for the EFI image.
516 @param[in] SystemTable A pointer to the EFI System Table.
518 @retval EFI_SUCCESS The entry point is executed successfully.
519 @retval other Some error occurs when executing this entry point.
524 SerialDxeInitialize (
525 IN EFI_HANDLE ImageHandle
,
526 IN EFI_SYSTEM_TABLE
*SystemTable
531 mSerialIoMode
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
532 mSerialIoMode
.DataBits
= (UINT32
) PcdGet8 (PcdUartDefaultDataBits
);
533 mSerialIoMode
.Parity
= (UINT32
) PcdGet8 (PcdUartDefaultParity
);
534 mSerialIoMode
.StopBits
= (UINT32
) PcdGet8 (PcdUartDefaultStopBits
);
535 mSerialIoMode
.ReceiveFifoDepth
= PcdGet16 (PcdUartDefaultReceiveFifoDepth
);
536 mSerialDevicePath
.Uart
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
537 mSerialDevicePath
.Uart
.DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
538 mSerialDevicePath
.Uart
.Parity
= PcdGet8 (PcdUartDefaultParity
);
539 mSerialDevicePath
.Uart
.StopBits
= PcdGet8 (PcdUartDefaultStopBits
);
542 // Issue a reset to initialize the Serial Port
544 Status
= mSerialIoTemplate
.Reset (&mSerialIoTemplate
);
545 if (EFI_ERROR (Status
)) {
550 // Make a new handle with Serial IO protocol and its device path on it.
552 Status
= gBS
->InstallMultipleProtocolInterfaces (
554 &gEfiSerialIoProtocolGuid
, &mSerialIoTemplate
,
555 &gEfiDevicePathProtocolGuid
, &mSerialDevicePath
,
558 ASSERT_EFI_ERROR (Status
);