From 7d49ced0cf64fbb3abf6b4d97dac4806bd1d9ee6 Mon Sep 17 00:00:00 2001 From: oliviermartin Date: Fri, 28 Sep 2012 10:56:12 +0000 Subject: EmbeddedPkg: Introduced 'SerialPortExtLib.h' EmbeddedPkg/SerialDxe was not allowing to set/get the control of the Serial connection because the needed functions were not exposed in SerialPortLib.h. This commit introduces an additional library to extend the SerialPort features. Signed-off-by: Olivier Martin git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13773 6f19259b-4bc3-4df7-8a09-765794883524 --- EmbeddedPkg/Include/Library/SerialPortExtLib.h | 66 ++++++++ .../TemplateSerialPortLib/TemplateSerialPortLib.c | 67 +++++++- EmbeddedPkg/SerialDxe/SerialDxe.inf | 7 +- EmbeddedPkg/SerialDxe/SerialIo.c | 182 ++++++++++++++++----- 4 files changed, 273 insertions(+), 49 deletions(-) create mode 100644 EmbeddedPkg/Include/Library/SerialPortExtLib.h (limited to 'EmbeddedPkg') diff --git a/EmbeddedPkg/Include/Library/SerialPortExtLib.h b/EmbeddedPkg/Include/Library/SerialPortExtLib.h new file mode 100644 index 0000000000..74f5e4c58c --- /dev/null +++ b/EmbeddedPkg/Include/Library/SerialPortExtLib.h @@ -0,0 +1,66 @@ +/** @file + + Copyright (c) 2012, ARM Ltd. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SERIAL_PORT_EXT_LIB_H__ +#define __SERIAL_PORT_EXT_LIB_H__ + +#include +#include + +/** + Set the serial device control bits. + + @return Always return EFI_UNSUPPORTED. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetControl ( + IN UINT32 Control + ); + +/** + Get the serial device control bits. + + @param Control Control signals read from the serial device. + + @retval EFI_SUCCESS The control bits were read from the serial device. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortGetControl ( + OUT UINT32 *Control + ); + +/** + Set the serial device attributes. + + @return Always return EFI_UNSUPPORTED. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetAttributes ( + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ); + +#endif + diff --git a/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.c b/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.c index 9cc2b79a8c..0110189abd 100644 --- a/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.c +++ b/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.c @@ -2,6 +2,7 @@ Serial I/O Port library functions with no library constructor/destructor Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ Copyright (c) 2012, ARM Ltd. All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -17,8 +18,9 @@ #include +#include -/* +/** Programmed hardware of Serial port. @@ -34,6 +36,65 @@ SerialPortInitialize ( return RETURN_UNSUPPORTED; } +/** + Set the serial device control bits. + + @return Always return EFI_UNSUPPORTED. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetControl ( + IN UINT32 Control + ) +{ + return RETURN_UNSUPPORTED; +} + +/** + Get the serial device control bits. + + @param Control Control signals read from the serial device. + + @retval EFI_SUCCESS The control bits were read from the serial device. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortGetControl ( + OUT UINT32 *Control + ) +{ + if (SerialPortPoll ()) { + // If a character is pending don't set EFI_SERIAL_INPUT_BUFFER_EMPTY + *Control = EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } else { + *Control = EFI_SERIAL_INPUT_BUFFER_EMPTY | EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } + return EFI_SUCCESS; +} + +/** + Set the serial device attributes. + + @return Always return EFI_UNSUPPORTED. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetAttributes ( + IN OUT UINT64 *BaudRate, + IN OUT UINT32 *ReceiveFifoDepth, + IN OUT UINT32 *Timeout, + IN OUT EFI_PARITY_TYPE *Parity, + IN OUT UINT8 *DataBits, + IN OUT EFI_STOP_BITS_TYPE *StopBits + ) +{ + return RETURN_UNSUPPORTED; +} + /** Write data to serial device. @@ -49,7 +110,7 @@ EFIAPI SerialPortWrite ( IN UINT8 *Buffer, IN UINTN NumberOfBytes -) + ) { return 0; } @@ -70,7 +131,7 @@ EFIAPI SerialPortRead ( OUT UINT8 *Buffer, IN UINTN NumberOfBytes -) + ) { return 0; } diff --git a/EmbeddedPkg/SerialDxe/SerialDxe.inf b/EmbeddedPkg/SerialDxe/SerialDxe.inf index e0aa57d311..37e8e0e008 100644 --- a/EmbeddedPkg/SerialDxe/SerialDxe.inf +++ b/EmbeddedPkg/SerialDxe/SerialDxe.inf @@ -22,13 +22,12 @@ ENTRY_POINT = SerialDxeInitialize - [Sources.common] SerialIo.c - [Packages] MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec [LibraryClasses] BaseLib @@ -41,9 +40,6 @@ UefiDriverEntryPoint SerialPortLib -[Guids] - - [Protocols] gEfiSerialIoProtocolGuid gEfiDevicePathProtocolGuid @@ -54,6 +50,5 @@ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits - [Depex] TRUE diff --git a/EmbeddedPkg/SerialDxe/SerialIo.c b/EmbeddedPkg/SerialDxe/SerialIo.c index ef4e6a1910..a94bacaf40 100644 --- a/EmbeddedPkg/SerialDxe/SerialIo.c +++ b/EmbeddedPkg/SerialDxe/SerialIo.c @@ -23,10 +23,35 @@ #include #include #include +#include #include #include +typedef struct { + VENDOR_DEVICE_PATH Guid; + UART_DEVICE_PATH Uart; + EFI_DEVICE_PATH_PROTOCOL End; +} SIMPLE_TEXT_OUT_DEVICE_PATH; + +SIMPLE_TEXT_OUT_DEVICE_PATH mDevicePath = { + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH), 0}, + EFI_CALLER_ID_GUID // Use the drivers GUID + }, + { + { MESSAGING_DEVICE_PATH, MSG_UART_DP, sizeof (UART_DEVICE_PATH), 0}, + 0, // Reserved + FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate + FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits + FixedPcdGet8 (PcdUartDefaultParity), // Parity (N) + FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits + }, + { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} +}; + +EFI_HANDLE gHandle = NULL; + /** Reset the serial device. @@ -42,8 +67,60 @@ SerialReset ( IN EFI_SERIAL_IO_PROTOCOL *This ) { - SerialPortInitialize (); - return EFI_SUCCESS; + EFI_STATUS Status; + EFI_TPL Tpl; + + Status = SerialPortInitialize (); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Set the Serial I/O mode and update the device path + // + + Tpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // Set the Serial I/O mode + // + This->Mode->ReceiveFifoDepth = 0; + This->Mode->Timeout = 1000000; + This->Mode->BaudRate = PcdGet64 (PcdUartDefaultBaudRate); + This->Mode->DataBits = (UINT32)PcdGet8 (PcdUartDefaultDataBits); + This->Mode->Parity = (UINT32)PcdGet8 (PcdUartDefaultParity); + This->Mode->StopBits = (UINT32)PcdGet8 (PcdUartDefaultStopBits); + + // + // Check if the device path has actually changed + // + if (mDevicePath.Uart.BaudRate == This->Mode->BaudRate && + mDevicePath.Uart.DataBits == (UINT8)This->Mode->DataBits && + mDevicePath.Uart.Parity == (UINT8)This->Mode->Parity && + mDevicePath.Uart.StopBits == (UINT8)This->Mode->StopBits + ) { + gBS->RestoreTPL (Tpl); + return EFI_SUCCESS; + } + + // + // Update the device path + // + mDevicePath.Uart.BaudRate = This->Mode->BaudRate; + mDevicePath.Uart.DataBits = (UINT8)This->Mode->DataBits; + mDevicePath.Uart.Parity = (UINT8)This->Mode->Parity; + mDevicePath.Uart.StopBits = (UINT8)This->Mode->StopBits; + + Status = gBS->ReinstallProtocolInterface ( + gHandle, + &gEfiDevicePathProtocolGuid, + &mDevicePath, + &mDevicePath + ); + + gBS->RestoreTPL (Tpl); + + return Status; } @@ -85,7 +162,60 @@ SerialSetAttributes ( IN EFI_STOP_BITS_TYPE StopBits ) { - return EFI_UNSUPPORTED; + EFI_STATUS Status; + EFI_TPL Tpl; + + Status = SerialPortSetAttributes (BaudRate, ReceiveFifoDepth, Timeout, Parity, DataBits, StopBits); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Set the Serial I/O mode and update the device path + // + + Tpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // Set the Serial I/O mode + // + This->Mode->BaudRate = BaudRate; + This->Mode->ReceiveFifoDepth = ReceiveFifoDepth; + This->Mode->Timeout = Timeout; + This->Mode->Parity = (UINT32)Parity; + This->Mode->DataBits = (UINT32)DataBits; + This->Mode->StopBits = (UINT32)StopBits; + + // + // Check if the device path has actually changed + // + if (mDevicePath.Uart.BaudRate == BaudRate && + mDevicePath.Uart.Parity == (UINT8)Parity && + mDevicePath.Uart.DataBits == DataBits && + mDevicePath.Uart.StopBits == (UINT8)StopBits + ) { + gBS->RestoreTPL (Tpl); + return EFI_SUCCESS; + } + + // + // Update the device path + // + mDevicePath.Uart.BaudRate = BaudRate; + mDevicePath.Uart.DataBits = DataBits; + mDevicePath.Uart.Parity = (UINT8) Parity; + mDevicePath.Uart.StopBits = (UINT8) StopBits; + + Status = gBS->ReinstallProtocolInterface ( + gHandle, + &gEfiDevicePathProtocolGuid, + &mDevicePath, + &mDevicePath + ); + + gBS->RestoreTPL (Tpl); + + return Status; } @@ -107,7 +237,7 @@ SerialSetControl ( IN UINT32 Control ) { - return EFI_UNSUPPORTED; + return SerialPortSetControl(Control); } @@ -128,13 +258,7 @@ SerialGetControl ( OUT UINT32 *Control ) { - if (SerialPortPoll ()) { - // If a character is pending don't set EFI_SERIAL_INPUT_BUFFER_EMPTY - *Control = EFI_SERIAL_OUTPUT_BUFFER_EMPTY; - } else { - *Control = EFI_SERIAL_INPUT_BUFFER_EMPTY | EFI_SERIAL_OUTPUT_BUFFER_EMPTY; - } - return EFI_SUCCESS; + return SerialPortGetControl(Control); } @@ -162,8 +286,13 @@ SerialWrite ( UINTN Count; Count = SerialPortWrite (Buffer, *BufferSize); - *BufferSize = Count; - return (Count == 0) ? EFI_DEVICE_ERROR : EFI_SUCCESS; + + if (Count != *BufferSize) { + *BufferSize = Count; + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; } /** @@ -202,9 +331,6 @@ SerialRead ( return EFI_SUCCESS; } - -EFI_HANDLE gHandle = NULL; - // // Template used to initialize the GDB Serial IO protocols // @@ -229,29 +355,6 @@ EFI_SERIAL_IO_PROTOCOL gSerialIoTemplate = { SerialRead, &gSerialIoMode }; - -typedef struct { - VENDOR_DEVICE_PATH Guid; - UART_DEVICE_PATH Uart; - EFI_DEVICE_PATH_PROTOCOL End; -} SIMPLE_TEXT_OUT_DEVICE_PATH; - -SIMPLE_TEXT_OUT_DEVICE_PATH mDevicePath = { - { - { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH), 0}, - EFI_CALLER_ID_GUID // Use the drivers GUID - }, - { - { MESSAGING_DEVICE_PATH, MSG_UART_DP, sizeof (UART_DEVICE_PATH), 0}, - 0, // Reserved - FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate - FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits - FixedPcdGet8 (PcdUartDefaultParity), // Parity (N) - FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits - }, - { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} -}; - /** Initialize the state information for the Serial Io Protocol @@ -273,7 +376,6 @@ SerialDxeInitialize ( { EFI_STATUS Status; - // Make a new handle with Serial IO protocol and its device path on it. Status = gBS->InstallMultipleProtocolInterfaces ( &gHandle, -- cgit v1.2.3