/** @file\r
Serial IO Abstraction for GDB stub. This allows an EFI consoles that shows up on the system \r
- running GDB. One consle for error information and another console for user input/output.\r
- \r
- Basic packet format is $packet-data#checksum. So every comand has 4 bytes of overhead: $, \r
+ running GDB. One console for error information and another console for user input/output.\r
+\r
+ Basic packet format is $packet-data#checksum. So every command has 4 bytes of overhead: $,\r
#, 0, 0. The 0 and 0 are the ascii characters for the checksum. \r
- \r
\r
- Copyright (c) 2008-2009, Apple Inc. All rights reserved.\r
- \r
- All rights reserved. This program and the accompanying materials\r
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+ Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>\r
+\r
+ This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
http://opensource.org/licenses/bsd-license.php\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/DebugLib.h>\r
#include <Library/SerialPortLib.h>\r
+#include <Library/SerialPortExtLib.h>\r
+#include <Library/PcdLib.h>\r
\r
#include <Protocol/SerialIo.h>\r
\r
+typedef struct {\r
+ VENDOR_DEVICE_PATH Guid;\r
+ UART_DEVICE_PATH Uart;\r
+ EFI_DEVICE_PATH_PROTOCOL End;\r
+} SIMPLE_TEXT_OUT_DEVICE_PATH;\r
+\r
+SIMPLE_TEXT_OUT_DEVICE_PATH mDevicePath = {\r
+ {\r
+ { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH), 0} },\r
+ EFI_CALLER_ID_GUID // Use the drivers GUID\r
+ },\r
+ {\r
+ { MESSAGING_DEVICE_PATH, MSG_UART_DP, { sizeof (UART_DEVICE_PATH), 0} },\r
+ 0, // Reserved\r
+ FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate\r
+ FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits\r
+ FixedPcdGet8 (PcdUartDefaultParity), // Parity (N)\r
+ FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits\r
+ },\r
+ { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } }\r
+};\r
+\r
+EFI_HANDLE gHandle = NULL;\r
+\r
/**\r
Reset the serial device.\r
\r
IN EFI_SERIAL_IO_PROTOCOL *This\r
)\r
{\r
- SerialPortInitialize ();\r
- return EFI_SUCCESS;\r
+ EFI_STATUS Status;\r
+ EFI_TPL Tpl;\r
+\r
+ Status = SerialPortInitialize ();\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Set the Serial I/O mode and update the device path\r
+ //\r
+\r
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+ //\r
+ // Set the Serial I/O mode\r
+ //\r
+ This->Mode->ReceiveFifoDepth = 0;\r
+ This->Mode->Timeout = 1000000;\r
+ This->Mode->BaudRate = PcdGet64 (PcdUartDefaultBaudRate);\r
+ This->Mode->DataBits = (UINT32)PcdGet8 (PcdUartDefaultDataBits);\r
+ This->Mode->Parity = (UINT32)PcdGet8 (PcdUartDefaultParity);\r
+ This->Mode->StopBits = (UINT32)PcdGet8 (PcdUartDefaultStopBits);\r
+\r
+ //\r
+ // Check if the device path has actually changed\r
+ //\r
+ if (mDevicePath.Uart.BaudRate == This->Mode->BaudRate &&\r
+ mDevicePath.Uart.DataBits == (UINT8)This->Mode->DataBits &&\r
+ mDevicePath.Uart.Parity == (UINT8)This->Mode->Parity &&\r
+ mDevicePath.Uart.StopBits == (UINT8)This->Mode->StopBits\r
+ ) {\r
+ gBS->RestoreTPL (Tpl);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Update the device path\r
+ //\r
+ mDevicePath.Uart.BaudRate = This->Mode->BaudRate;\r
+ mDevicePath.Uart.DataBits = (UINT8)This->Mode->DataBits;\r
+ mDevicePath.Uart.Parity = (UINT8)This->Mode->Parity;\r
+ mDevicePath.Uart.StopBits = (UINT8)This->Mode->StopBits;\r
+\r
+ Status = gBS->ReinstallProtocolInterface (\r
+ gHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ &mDevicePath,\r
+ &mDevicePath\r
+ );\r
+\r
+ gBS->RestoreTPL (Tpl);\r
+\r
+ return Status;\r
}\r
\r
\r
/**\r
- Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, \r
+ Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,\r
data buts, and stop bits on a serial device.\r
\r
@param This Protocol instance pointer.\r
@param BaudRate The requested baud rate. A BaudRate value of 0 will use the the\r
device's default interface speed.\r
- @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the\r
+ @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the\r
serial interface. A ReceiveFifoDepth value of 0 will use\r
- the device's dfault FIFO depth.\r
+ the device's default FIFO depth.\r
@param Timeout The requested time out for a single character in microseconds.\r
This timeout applies to both the transmit and receive side of the\r
interface. A Timeout value of 0 will use the device's default time\r
@param Parity The type of parity to use on this serial device. A Parity value of\r
DefaultParity will use the device's default parity value.\r
@param DataBits The number of data bits to use on the serial device. A DataBits\r
- vaule of 0 will use the device's default data bit setting.\r
+ value of 0 will use the device's default data bit setting.\r
@param StopBits The number of stop bits to use on this serial device. A StopBits\r
value of DefaultStopBits will use the device's default number of\r
stop bits.\r
IN EFI_STOP_BITS_TYPE StopBits\r
)\r
{\r
- return EFI_UNSUPPORTED;\r
+ RETURN_STATUS ReturnStatus;\r
+ EFI_STATUS Status;\r
+ EFI_TPL Tpl;\r
+\r
+ ReturnStatus = SerialPortSetAttributes (&BaudRate, &ReceiveFifoDepth, &Timeout, &Parity, &DataBits, &StopBits);\r
+ if (RETURN_ERROR (ReturnStatus)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ //\r
+ // Set the Serial I/O mode and update the device path\r
+ //\r
+\r
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+ //\r
+ // Set the Serial I/O mode\r
+ //\r
+ This->Mode->BaudRate = BaudRate;\r
+ This->Mode->ReceiveFifoDepth = ReceiveFifoDepth;\r
+ This->Mode->Timeout = Timeout;\r
+ This->Mode->Parity = (UINT32)Parity;\r
+ This->Mode->DataBits = (UINT32)DataBits;\r
+ This->Mode->StopBits = (UINT32)StopBits;\r
+\r
+ //\r
+ // Check if the device path has actually changed\r
+ //\r
+ if (mDevicePath.Uart.BaudRate == BaudRate &&\r
+ mDevicePath.Uart.Parity == (UINT8)Parity &&\r
+ mDevicePath.Uart.DataBits == DataBits &&\r
+ mDevicePath.Uart.StopBits == (UINT8)StopBits\r
+ ) {\r
+ gBS->RestoreTPL (Tpl);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Update the device path\r
+ //\r
+ mDevicePath.Uart.BaudRate = BaudRate;\r
+ mDevicePath.Uart.DataBits = DataBits;\r
+ mDevicePath.Uart.Parity = (UINT8) Parity;\r
+ mDevicePath.Uart.StopBits = (UINT8) StopBits;\r
+\r
+ Status = gBS->ReinstallProtocolInterface (\r
+ gHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ &mDevicePath,\r
+ &mDevicePath\r
+ );\r
+\r
+ gBS->RestoreTPL (Tpl);\r
+\r
+ return Status;\r
}\r
\r
\r
IN UINT32 Control\r
)\r
{\r
- return EFI_UNSUPPORTED;\r
+ return SerialPortSetControl(Control);\r
}\r
\r
\r
/**\r
- Retrieves the status of thecontrol bits on a serial device\r
+ Retrieves the status of the control bits on a serial device\r
\r
@param This Protocol instance pointer.\r
@param Control A pointer to return the current Control signals from the serial device.\r
OUT UINT32 *Control\r
)\r
{\r
- if (SerialPortPoll ()) {\r
- // If a character is pending don't set EFI_SERIAL_INPUT_BUFFER_EMPTY\r
- *Control = EFI_SERIAL_OUTPUT_BUFFER_EMPTY;\r
- } else {\r
- *Control = EFI_SERIAL_INPUT_BUFFER_EMPTY | EFI_SERIAL_OUTPUT_BUFFER_EMPTY;\r
- }\r
- return EFI_SUCCESS;\r
+ return SerialPortGetControl(Control);\r
}\r
\r
\r
UINTN Count;\r
\r
Count = SerialPortWrite (Buffer, *BufferSize);\r
- *BufferSize = Count;\r
- return (Count == 0) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
+\r
+ if (Count != *BufferSize) {\r
+ *BufferSize = Count;\r
+ return EFI_TIMEOUT;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
- Writes data to a serial device.\r
+ Reads data from a serial device.\r
\r
@param This Protocol instance pointer.\r
@param BufferSize On input, the size of the Buffer. On output, the amount of\r
OUT VOID *Buffer\r
)\r
{\r
- UINTN Count;\r
- \r
- Count = SerialPortWrite (Buffer, *BufferSize);\r
- *BufferSize = Count;\r
- return (Count == 0) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
-}\r
+ UINTN Count = 0;\r
\r
+ if (SerialPortPoll()) {\r
+ Count = SerialPortRead (Buffer, *BufferSize);\r
+ }\r
\r
-EFI_HANDLE gHandle = NULL;\r
+ if (Count != *BufferSize) {\r
+ *BufferSize = Count;\r
+ return EFI_TIMEOUT;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
\r
// \r
-// Template used to initailize the GDB Serial IO protocols\r
+// Template used to initialize the GDB Serial IO protocols\r
//\r
EFI_SERIAL_IO_MODE gSerialIoMode = {\r
- 0, // ControlMask\r
- 0, // Timeout\r
- 0, // BaudRate\r
- 1, // RceiveFifoDepth\r
- 0, // DataBits\r
- 0, // Parity\r
- 0 // StopBits\r
+ 0, // ControlMask\r
+ 0, // Timeout\r
+ FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate\r
+ 1, // ReceiveFifoDepth\r
+ FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits\r
+ FixedPcdGet8 (PcdUartDefaultParity), // Parity\r
+ FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits\r
};\r
\r
\r
SerialRead,\r
&gSerialIoMode\r
};\r
- \r
\r
/**\r
Initialize the state information for the Serial Io Protocol\r
{\r
EFI_STATUS Status;\r
\r
-\r
// Make a new handle with Serial IO protocol and its device path on it.\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
&gHandle, \r
&gEfiSerialIoProtocolGuid, &gSerialIoTemplate,\r
- &gEfiDevicePathProtocolGuid, NULL, // BugBug: Need a device path\r
+ &gEfiDevicePathProtocolGuid, &mDevicePath, \r
NULL\r
);\r
ASSERT_EFI_ERROR (Status);\r