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>
21 VENDOR_DEVICE_PATH Guid
;
22 UART_DEVICE_PATH Uart
;
23 EFI_DEVICE_PATH_PROTOCOL End
;
27 Reset the serial device.
29 @param This Protocol instance pointer.
31 @retval EFI_SUCCESS The device was reset.
32 @retval EFI_DEVICE_ERROR The serial device could not be reset.
38 IN EFI_SERIAL_IO_PROTOCOL
*This
42 Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
43 data bits, and stop bits on a serial device.
45 @param This Protocol instance pointer.
46 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
47 device's default interface speed.
48 @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the
49 serial interface. A ReceiveFifoDepth value of 0 will use
50 the device's default FIFO depth.
51 @param Timeout The requested time out for a single character in microseconds.
52 This timeout applies to both the transmit and receive side of the
53 interface. A Timeout value of 0 will use the device's default time
55 @param Parity The type of parity to use on this serial device. A Parity value of
56 DefaultParity will use the device's default parity value.
57 @param DataBits The number of data bits to use on the serial device. A DataBits
58 value of 0 will use the device's default data bit setting.
59 @param StopBits The number of stop bits to use on this serial device. A StopBits
60 value of DefaultStopBits will use the device's default number of
63 @retval EFI_SUCCESS The device was reset.
64 @retval EFI_INVALID_PARAMETER One or more attributes has an unsupported value.
65 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
71 IN EFI_SERIAL_IO_PROTOCOL
*This
,
73 IN UINT32 ReceiveFifoDepth
,
75 IN EFI_PARITY_TYPE Parity
,
77 IN EFI_STOP_BITS_TYPE StopBits
81 Set the control bits on a serial device
83 @param This Protocol instance pointer.
84 @param Control Set the bits of Control that are settable.
86 @retval EFI_SUCCESS The new control bits were set on the serial device.
87 @retval EFI_UNSUPPORTED The serial device does not support this operation.
88 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
94 IN EFI_SERIAL_IO_PROTOCOL
*This
,
99 Retrieves the status of the control bits on a serial device
101 @param This Protocol instance pointer.
102 @param Control A pointer to return the current Control signals from the serial device.
104 @retval EFI_SUCCESS The control bits were read from the serial device.
105 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
111 IN EFI_SERIAL_IO_PROTOCOL
*This
,
116 Writes data to a serial device.
118 @param This Protocol instance pointer.
119 @param BufferSize On input, the size of the Buffer. On output, the amount of
120 data actually written.
121 @param Buffer The buffer of data to write
123 @retval EFI_SUCCESS The data was written.
124 @retval EFI_DEVICE_ERROR The device reported an error.
125 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
131 IN EFI_SERIAL_IO_PROTOCOL
*This
,
132 IN OUT UINTN
*BufferSize
,
137 Reads data from a serial device.
139 @param This Protocol instance pointer.
140 @param BufferSize On input, the size of the Buffer. On output, the amount of
141 data returned in Buffer.
142 @param Buffer The buffer to return the data into.
144 @retval EFI_SUCCESS The data was read.
145 @retval EFI_DEVICE_ERROR The device reported an error.
146 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
152 IN EFI_SERIAL_IO_PROTOCOL
*This
,
153 IN OUT UINTN
*BufferSize
,
157 EFI_HANDLE mSerialHandle
= NULL
;
159 SERIAL_DEVICE_PATH mSerialDevicePath
= {
161 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, { sizeof (VENDOR_DEVICE_PATH
), 0} },
162 EFI_CALLER_ID_GUID
// Use the driver's GUID
165 { MESSAGING_DEVICE_PATH
, MSG_UART_DP
, { sizeof (UART_DEVICE_PATH
), 0} },
172 { END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
, { sizeof (EFI_DEVICE_PATH_PROTOCOL
), 0 } }
176 // Template used to initialize the Serial IO protocols.
178 EFI_SERIAL_IO_MODE mSerialIoMode
= {
180 // value field set in SerialDxeInitialize()?
181 //--------- ------------------- -----------------------------
183 1000 * 1000, // Timeout
185 1, // ReceiveFifoDepth
191 EFI_SERIAL_IO_PROTOCOL mSerialIoTemplate
= {
192 SERIAL_IO_INTERFACE_REVISION
,
203 Reset the serial device.
205 @param This Protocol instance pointer.
207 @retval EFI_SUCCESS The device was reset.
208 @retval EFI_DEVICE_ERROR The serial device could not be reset.
214 IN EFI_SERIAL_IO_PROTOCOL
*This
219 Status
= SerialPortInitialize ();
220 if (EFI_ERROR (Status
)) {
225 // Go set the current attributes
227 Status
= This
->SetAttributes (
229 This
->Mode
->BaudRate
,
230 This
->Mode
->ReceiveFifoDepth
,
232 (EFI_PARITY_TYPE
) This
->Mode
->Parity
,
233 (UINT8
) This
->Mode
->DataBits
,
234 (EFI_STOP_BITS_TYPE
) This
->Mode
->StopBits
238 // The serial device may not support some of the attributes. To prevent
239 // later failure, always return EFI_SUCCESS when SetAttributes is returning
240 // EFI_INVALID_PARAMETER.
242 if (Status
== EFI_INVALID_PARAMETER
) {
250 Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
251 data bits, and stop bits on a serial device.
253 @param This Protocol instance pointer.
254 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
255 device's default interface speed.
256 @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the
257 serial interface. A ReceiveFifoDepth value of 0 will use
258 the device's default FIFO depth.
259 @param Timeout The requested time out for a single character in microseconds.
260 This timeout applies to both the transmit and receive side of the
261 interface. A Timeout value of 0 will use the device's default time
263 @param Parity The type of parity to use on this serial device. A Parity value of
264 DefaultParity will use the device's default parity value.
265 @param DataBits The number of data bits to use on the serial device. A DataBits
266 value of 0 will use the device's default data bit setting.
267 @param StopBits The number of stop bits to use on this serial device. A StopBits
268 value of DefaultStopBits will use the device's default number of
271 @retval EFI_SUCCESS The device was reset.
272 @retval EFI_INVALID_PARAMETER One or more attributes has an unsupported value.
273 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
278 SerialSetAttributes (
279 IN EFI_SERIAL_IO_PROTOCOL
*This
,
281 IN UINT32 ReceiveFifoDepth
,
283 IN EFI_PARITY_TYPE Parity
,
285 IN EFI_STOP_BITS_TYPE StopBits
290 UINT64 OriginalBaudRate
;
291 UINT32 OriginalReceiveFifoDepth
;
292 UINT32 OriginalTimeout
;
293 EFI_PARITY_TYPE OriginalParity
;
294 UINT8 OriginalDataBits
;
295 EFI_STOP_BITS_TYPE OriginalStopBits
;
298 // Preserve the original input values in case
299 // SerialPortSetAttributes() updates the input/output
300 // parameters even on error.
302 OriginalBaudRate
= BaudRate
;
303 OriginalReceiveFifoDepth
= ReceiveFifoDepth
;
304 OriginalTimeout
= Timeout
;
305 OriginalParity
= Parity
;
306 OriginalDataBits
= DataBits
;
307 OriginalStopBits
= StopBits
;
308 Status
= SerialPortSetAttributes (&BaudRate
, &ReceiveFifoDepth
, &Timeout
, &Parity
, &DataBits
, &StopBits
);
309 if (EFI_ERROR (Status
)) {
311 // If it is just to set Timeout value and unsupported is returned,
312 // do not return error.
314 if ((Status
== EFI_UNSUPPORTED
) &&
315 (This
->Mode
->Timeout
!= OriginalTimeout
) &&
316 (This
->Mode
->ReceiveFifoDepth
== OriginalReceiveFifoDepth
) &&
317 (This
->Mode
->BaudRate
== OriginalBaudRate
) &&
318 (This
->Mode
->DataBits
== (UINT32
) OriginalDataBits
) &&
319 (This
->Mode
->Parity
== (UINT32
) OriginalParity
) &&
320 (This
->Mode
->StopBits
== (UINT32
) OriginalStopBits
)) {
322 // Restore to the original input values.
324 BaudRate
= OriginalBaudRate
;
325 ReceiveFifoDepth
= OriginalReceiveFifoDepth
;
326 Timeout
= OriginalTimeout
;
327 Parity
= OriginalParity
;
328 DataBits
= OriginalDataBits
;
329 StopBits
= OriginalStopBits
;
330 Status
= EFI_SUCCESS
;
331 } else if (Status
== EFI_INVALID_PARAMETER
|| Status
== EFI_UNSUPPORTED
) {
332 return EFI_INVALID_PARAMETER
;
334 return EFI_DEVICE_ERROR
;
339 // Set the Serial I/O mode and update the device path
342 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
345 // Set the Serial I/O mode
347 This
->Mode
->ReceiveFifoDepth
= ReceiveFifoDepth
;
348 This
->Mode
->Timeout
= Timeout
;
349 This
->Mode
->BaudRate
= BaudRate
;
350 This
->Mode
->DataBits
= (UINT32
) DataBits
;
351 This
->Mode
->Parity
= (UINT32
) Parity
;
352 This
->Mode
->StopBits
= (UINT32
) StopBits
;
355 // Check if the device path has actually changed
357 if (mSerialDevicePath
.Uart
.BaudRate
== BaudRate
&&
358 mSerialDevicePath
.Uart
.DataBits
== DataBits
&&
359 mSerialDevicePath
.Uart
.Parity
== (UINT8
) Parity
&&
360 mSerialDevicePath
.Uart
.StopBits
== (UINT8
) StopBits
362 gBS
->RestoreTPL (Tpl
);
367 // Update the device path
369 mSerialDevicePath
.Uart
.BaudRate
= BaudRate
;
370 mSerialDevicePath
.Uart
.DataBits
= DataBits
;
371 mSerialDevicePath
.Uart
.Parity
= (UINT8
) Parity
;
372 mSerialDevicePath
.Uart
.StopBits
= (UINT8
) StopBits
;
374 Status
= gBS
->ReinstallProtocolInterface (
376 &gEfiDevicePathProtocolGuid
,
381 gBS
->RestoreTPL (Tpl
);
387 Set the control bits on a serial device
389 @param This Protocol instance pointer.
390 @param Control Set the bits of Control that are settable.
392 @retval EFI_SUCCESS The new control bits were set on the serial device.
393 @retval EFI_UNSUPPORTED The serial device does not support this operation.
394 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
400 IN EFI_SERIAL_IO_PROTOCOL
*This
,
404 return SerialPortSetControl (Control
);
408 Retrieves the status of the control bits on a serial device
410 @param This Protocol instance pointer.
411 @param Control A pointer to return the current Control signals from the serial device.
413 @retval EFI_SUCCESS The control bits were read from the serial device.
414 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
420 IN EFI_SERIAL_IO_PROTOCOL
*This
,
424 return SerialPortGetControl (Control
);
428 Writes data to a serial device.
430 @param This Protocol instance pointer.
431 @param BufferSize On input, the size of the Buffer. On output, the amount of
432 data actually written.
433 @param Buffer The buffer of data to write
435 @retval EFI_SUCCESS The data was written.
436 @retval EFI_DEVICE_ERROR The device reported an error.
437 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
443 IN EFI_SERIAL_IO_PROTOCOL
*This
,
444 IN OUT UINTN
*BufferSize
,
450 Count
= SerialPortWrite (Buffer
, *BufferSize
);
452 if (Count
!= *BufferSize
) {
461 Reads data from a serial device.
463 @param This Protocol instance pointer.
464 @param BufferSize On input, the size of the Buffer. On output, the amount of
465 data returned in Buffer.
466 @param Buffer The buffer to return the data into.
468 @retval EFI_SUCCESS The data was read.
469 @retval EFI_DEVICE_ERROR The device reported an error.
470 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
476 IN EFI_SERIAL_IO_PROTOCOL
*This
,
477 IN OUT UINTN
*BufferSize
,
486 while (Count
< *BufferSize
) {
488 while (TimeOut
< mSerialIoMode
.Timeout
) {
489 if (SerialPortPoll ()) {
495 if (TimeOut
>= mSerialIoMode
.Timeout
) {
498 SerialPortRead (Buffer
, 1);
500 Buffer
= (VOID
*) ((UINT8
*) Buffer
+ 1);
503 if (Count
!= *BufferSize
) {
512 Initialization for the Serial Io Protocol.
514 @param[in] ImageHandle The firmware allocated handle for the EFI image.
515 @param[in] SystemTable A pointer to the EFI System Table.
517 @retval EFI_SUCCESS The entry point is executed successfully.
518 @retval other Some error occurs when executing this entry point.
523 SerialDxeInitialize (
524 IN EFI_HANDLE ImageHandle
,
525 IN EFI_SYSTEM_TABLE
*SystemTable
530 mSerialIoMode
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
531 mSerialIoMode
.DataBits
= (UINT32
) PcdGet8 (PcdUartDefaultDataBits
);
532 mSerialIoMode
.Parity
= (UINT32
) PcdGet8 (PcdUartDefaultParity
);
533 mSerialIoMode
.StopBits
= (UINT32
) PcdGet8 (PcdUartDefaultStopBits
);
534 mSerialIoMode
.ReceiveFifoDepth
= PcdGet16 (PcdUartDefaultReceiveFifoDepth
);
535 mSerialDevicePath
.Uart
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
536 mSerialDevicePath
.Uart
.DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
537 mSerialDevicePath
.Uart
.Parity
= PcdGet8 (PcdUartDefaultParity
);
538 mSerialDevicePath
.Uart
.StopBits
= PcdGet8 (PcdUartDefaultStopBits
);
541 // Issue a reset to initialize the Serial Port
543 Status
= mSerialIoTemplate
.Reset (&mSerialIoTemplate
);
544 if (EFI_ERROR (Status
)) {
549 // Make a new handle with Serial IO protocol and its device path on it.
551 Status
= gBS
->InstallMultipleProtocolInterfaces (
553 &gEfiSerialIoProtocolGuid
, &mSerialIoTemplate
,
554 &gEfiDevicePathProtocolGuid
, &mSerialDevicePath
,
557 ASSERT_EFI_ERROR (Status
);