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 }
164 EDKII_SERIAL_PORT_LIB_VENDOR_GUID
167 { MESSAGING_DEVICE_PATH
, MSG_UART_DP
, { sizeof (UART_DEVICE_PATH
), 0 }
175 { END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
, { sizeof (EFI_DEVICE_PATH_PROTOCOL
), 0 }
180 // Template used to initialize the Serial IO protocols.
182 EFI_SERIAL_IO_MODE mSerialIoMode
= {
184 // value field set in SerialDxeInitialize()?
185 // --------- ------------------- -----------------------------
187 1000 * 1000, // Timeout
189 1, // ReceiveFifoDepth
195 EFI_SERIAL_IO_PROTOCOL mSerialIoTemplate
= {
196 SERIAL_IO_INTERFACE_REVISION
,
207 Reset the serial device.
209 @param This Protocol instance pointer.
211 @retval EFI_SUCCESS The device was reset.
212 @retval EFI_DEVICE_ERROR The serial device could not be reset.
218 IN EFI_SERIAL_IO_PROTOCOL
*This
223 Status
= SerialPortInitialize ();
224 if (EFI_ERROR (Status
)) {
229 // Go set the current attributes
231 Status
= This
->SetAttributes (
233 This
->Mode
->BaudRate
,
234 This
->Mode
->ReceiveFifoDepth
,
236 (EFI_PARITY_TYPE
)This
->Mode
->Parity
,
237 (UINT8
)This
->Mode
->DataBits
,
238 (EFI_STOP_BITS_TYPE
)This
->Mode
->StopBits
242 // The serial device may not support some of the attributes. To prevent
243 // later failure, always return EFI_SUCCESS when SetAttributes is returning
244 // EFI_INVALID_PARAMETER.
246 if (Status
== EFI_INVALID_PARAMETER
) {
254 Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
255 data bits, and stop bits on a serial device.
257 @param This Protocol instance pointer.
258 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
259 device's default interface speed.
260 @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the
261 serial interface. A ReceiveFifoDepth value of 0 will use
262 the device's default FIFO depth.
263 @param Timeout The requested time out for a single character in microseconds.
264 This timeout applies to both the transmit and receive side of the
265 interface. A Timeout value of 0 will use the device's default time
267 @param Parity The type of parity to use on this serial device. A Parity value of
268 DefaultParity will use the device's default parity value.
269 @param DataBits The number of data bits to use on the serial device. A DataBits
270 value of 0 will use the device's default data bit setting.
271 @param StopBits The number of stop bits to use on this serial device. A StopBits
272 value of DefaultStopBits will use the device's default number of
275 @retval EFI_SUCCESS The device was reset.
276 @retval EFI_INVALID_PARAMETER One or more attributes has an unsupported value.
277 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
282 SerialSetAttributes (
283 IN EFI_SERIAL_IO_PROTOCOL
*This
,
285 IN UINT32 ReceiveFifoDepth
,
287 IN EFI_PARITY_TYPE Parity
,
289 IN EFI_STOP_BITS_TYPE StopBits
294 UINT64 OriginalBaudRate
;
295 UINT32 OriginalReceiveFifoDepth
;
296 UINT32 OriginalTimeout
;
297 EFI_PARITY_TYPE OriginalParity
;
298 UINT8 OriginalDataBits
;
299 EFI_STOP_BITS_TYPE OriginalStopBits
;
302 // Preserve the original input values in case
303 // SerialPortSetAttributes() updates the input/output
304 // parameters even on error.
306 OriginalBaudRate
= BaudRate
;
307 OriginalReceiveFifoDepth
= ReceiveFifoDepth
;
308 OriginalTimeout
= Timeout
;
309 OriginalParity
= Parity
;
310 OriginalDataBits
= DataBits
;
311 OriginalStopBits
= StopBits
;
312 Status
= SerialPortSetAttributes (&BaudRate
, &ReceiveFifoDepth
, &Timeout
, &Parity
, &DataBits
, &StopBits
);
313 if (EFI_ERROR (Status
)) {
315 // If it is just to set Timeout value and unsupported is returned,
316 // do not return error.
318 if ((Status
== EFI_UNSUPPORTED
) &&
319 (This
->Mode
->Timeout
!= OriginalTimeout
) &&
320 (This
->Mode
->ReceiveFifoDepth
== OriginalReceiveFifoDepth
) &&
321 (This
->Mode
->BaudRate
== OriginalBaudRate
) &&
322 (This
->Mode
->DataBits
== (UINT32
)OriginalDataBits
) &&
323 (This
->Mode
->Parity
== (UINT32
)OriginalParity
) &&
324 (This
->Mode
->StopBits
== (UINT32
)OriginalStopBits
))
327 // Restore to the original input values.
329 BaudRate
= OriginalBaudRate
;
330 ReceiveFifoDepth
= OriginalReceiveFifoDepth
;
331 Timeout
= OriginalTimeout
;
332 Parity
= OriginalParity
;
333 DataBits
= OriginalDataBits
;
334 StopBits
= OriginalStopBits
;
335 Status
= EFI_SUCCESS
;
336 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
337 return EFI_INVALID_PARAMETER
;
339 return EFI_DEVICE_ERROR
;
344 // Set the Serial I/O mode and update the device path
347 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
350 // Set the Serial I/O mode
352 This
->Mode
->ReceiveFifoDepth
= ReceiveFifoDepth
;
353 This
->Mode
->Timeout
= Timeout
;
354 This
->Mode
->BaudRate
= BaudRate
;
355 This
->Mode
->DataBits
= (UINT32
)DataBits
;
356 This
->Mode
->Parity
= (UINT32
)Parity
;
357 This
->Mode
->StopBits
= (UINT32
)StopBits
;
360 // Check if the device path has actually changed
362 if ((mSerialDevicePath
.Uart
.BaudRate
== BaudRate
) &&
363 (mSerialDevicePath
.Uart
.DataBits
== DataBits
) &&
364 (mSerialDevicePath
.Uart
.Parity
== (UINT8
)Parity
) &&
365 (mSerialDevicePath
.Uart
.StopBits
== (UINT8
)StopBits
)
368 gBS
->RestoreTPL (Tpl
);
373 // Update the device path
375 mSerialDevicePath
.Uart
.BaudRate
= BaudRate
;
376 mSerialDevicePath
.Uart
.DataBits
= DataBits
;
377 mSerialDevicePath
.Uart
.Parity
= (UINT8
)Parity
;
378 mSerialDevicePath
.Uart
.StopBits
= (UINT8
)StopBits
;
380 Status
= gBS
->ReinstallProtocolInterface (
382 &gEfiDevicePathProtocolGuid
,
387 gBS
->RestoreTPL (Tpl
);
393 Set the control bits on a serial device
395 @param This Protocol instance pointer.
396 @param Control Set the bits of Control that are settable.
398 @retval EFI_SUCCESS The new control bits were set on the serial device.
399 @retval EFI_UNSUPPORTED The serial device does not support this operation.
400 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
406 IN EFI_SERIAL_IO_PROTOCOL
*This
,
410 return SerialPortSetControl (Control
);
414 Retrieves the status of the control bits on a serial device
416 @param This Protocol instance pointer.
417 @param Control A pointer to return the current Control signals from the serial device.
419 @retval EFI_SUCCESS The control bits were read from the serial device.
420 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
426 IN EFI_SERIAL_IO_PROTOCOL
*This
,
430 return SerialPortGetControl (Control
);
434 Writes data to a serial device.
436 @param This Protocol instance pointer.
437 @param BufferSize On input, the size of the Buffer. On output, the amount of
438 data actually written.
439 @param Buffer The buffer of data to write
441 @retval EFI_SUCCESS The data was written.
442 @retval EFI_DEVICE_ERROR The device reported an error.
443 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
449 IN EFI_SERIAL_IO_PROTOCOL
*This
,
450 IN OUT UINTN
*BufferSize
,
456 Count
= SerialPortWrite (Buffer
, *BufferSize
);
458 if (Count
!= *BufferSize
) {
467 Reads data from a serial device.
469 @param This Protocol instance pointer.
470 @param BufferSize On input, the size of the Buffer. On output, the amount of
471 data returned in Buffer.
472 @param Buffer The buffer to return the data into.
474 @retval EFI_SUCCESS The data was read.
475 @retval EFI_DEVICE_ERROR The device reported an error.
476 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
482 IN EFI_SERIAL_IO_PROTOCOL
*This
,
483 IN OUT UINTN
*BufferSize
,
492 while (Count
< *BufferSize
) {
494 while (TimeOut
< mSerialIoMode
.Timeout
) {
495 if (SerialPortPoll ()) {
503 if (TimeOut
>= mSerialIoMode
.Timeout
) {
507 SerialPortRead (Buffer
, 1);
509 Buffer
= (VOID
*)((UINT8
*)Buffer
+ 1);
512 if (Count
!= *BufferSize
) {
521 Initialization for the Serial Io Protocol.
523 @param[in] ImageHandle The firmware allocated handle for the EFI image.
524 @param[in] SystemTable A pointer to the EFI System Table.
526 @retval EFI_SUCCESS The entry point is executed successfully.
527 @retval other Some error occurs when executing this entry point.
532 SerialDxeInitialize (
533 IN EFI_HANDLE ImageHandle
,
534 IN EFI_SYSTEM_TABLE
*SystemTable
539 mSerialIoMode
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
540 mSerialIoMode
.DataBits
= (UINT32
)PcdGet8 (PcdUartDefaultDataBits
);
541 mSerialIoMode
.Parity
= (UINT32
)PcdGet8 (PcdUartDefaultParity
);
542 mSerialIoMode
.StopBits
= (UINT32
)PcdGet8 (PcdUartDefaultStopBits
);
543 mSerialIoMode
.ReceiveFifoDepth
= PcdGet16 (PcdUartDefaultReceiveFifoDepth
);
544 mSerialDevicePath
.Uart
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
545 mSerialDevicePath
.Uart
.DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
546 mSerialDevicePath
.Uart
.Parity
= PcdGet8 (PcdUartDefaultParity
);
547 mSerialDevicePath
.Uart
.StopBits
= PcdGet8 (PcdUartDefaultStopBits
);
550 // Issue a reset to initialize the Serial Port
552 Status
= mSerialIoTemplate
.Reset (&mSerialIoTemplate
);
553 if (EFI_ERROR (Status
)) {
558 // Make a new handle with Serial IO protocol and its device path on it.
560 Status
= gBS
->InstallMultipleProtocolInterfaces (
562 &gEfiSerialIoProtocolGuid
,
564 &gEfiDevicePathProtocolGuid
,
568 ASSERT_EFI_ERROR (Status
);