mirror of https://github.com/acidanthera/audk.git
723 lines
20 KiB
C
723 lines
20 KiB
C
|
/** @file
|
||
|
Install Serial IO Protocol that layers on top of a Debug Communication Library instance.
|
||
|
|
||
|
Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
|
||
|
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.
|
||
|
|
||
|
**/
|
||
|
|
||
|
#include "DxeDebugAgentLib.h"
|
||
|
|
||
|
//
|
||
|
// Serial I/O Protocol Interface defintions.
|
||
|
//
|
||
|
|
||
|
/**
|
||
|
Reset serial device.
|
||
|
|
||
|
@param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
|
||
|
|
||
|
@retval EFI_SUCCESS Reset successfully.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
SerialReset (
|
||
|
IN EFI_SERIAL_IO_PROTOCOL *This
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
Set new attributes to a serial device.
|
||
|
|
||
|
@param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
|
||
|
@param[in] BaudRate The baudrate of the serial device.
|
||
|
@param[in] ReceiveFifoDepth The depth of receive FIFO buffer.
|
||
|
@param[in] Timeout The request timeout for a single char.
|
||
|
@param[in] Parity The type of parity used in serial device.
|
||
|
@param[in] DataBits Number of databits used in serial device.
|
||
|
@param[in] StopBits Number of stopbits used in serial device.
|
||
|
|
||
|
@retval EFI_SUCCESS The new attributes were set.
|
||
|
@retval EFI_INVALID_PARAMETER One or more attributes have an unsupported value.
|
||
|
@retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return).
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
SerialSetAttributes (
|
||
|
IN EFI_SERIAL_IO_PROTOCOL *This,
|
||
|
IN UINT64 BaudRate,
|
||
|
IN UINT32 ReceiveFifoDepth,
|
||
|
IN UINT32 Timeout,
|
||
|
IN EFI_PARITY_TYPE Parity,
|
||
|
IN UINT8 DataBits,
|
||
|
IN EFI_STOP_BITS_TYPE StopBits
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
Set Control Bits.
|
||
|
|
||
|
@param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
|
||
|
@param[in] Control Control bits that can be settable.
|
||
|
|
||
|
@retval EFI_SUCCESS New Control bits were set successfully.
|
||
|
@retval EFI_UNSUPPORTED The Control bits wanted to set are not supported.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
SerialSetControl (
|
||
|
IN EFI_SERIAL_IO_PROTOCOL *This,
|
||
|
IN UINT32 Control
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
Get ControlBits.
|
||
|
|
||
|
@param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
|
||
|
@param[out] Control Control signals of the serial device.
|
||
|
|
||
|
@retval EFI_SUCCESS Get Control signals successfully.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
SerialGetControl (
|
||
|
IN EFI_SERIAL_IO_PROTOCOL *This,
|
||
|
OUT UINT32 *Control
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
Write the specified number of bytes to serial device.
|
||
|
|
||
|
@param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
|
||
|
@param[in, out] BufferSize On input the size of Buffer, on output the amount of
|
||
|
data actually written.
|
||
|
@param[in] Buffer The buffer of data to write.
|
||
|
|
||
|
@retval EFI_SUCCESS The data were written successfully.
|
||
|
@retval EFI_DEVICE_ERROR The device reported an error.
|
||
|
@retval EFI_TIMEOUT The write operation was stopped due to timeout.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
SerialWrite (
|
||
|
IN EFI_SERIAL_IO_PROTOCOL *This,
|
||
|
IN OUT UINTN *BufferSize,
|
||
|
IN VOID *Buffer
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
Read the specified number of bytes from serial device.
|
||
|
|
||
|
@param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
|
||
|
@param[in, out] BufferSize On input the size of Buffer, on output the amount of
|
||
|
data returned in buffer.
|
||
|
@param[out] Buffer The buffer to return the data into.
|
||
|
|
||
|
@retval EFI_SUCCESS The data were read successfully.
|
||
|
@retval EFI_DEVICE_ERROR The device reported an error.
|
||
|
@retval EFI_TIMEOUT The read operation was stopped due to timeout.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
SerialRead (
|
||
|
IN EFI_SERIAL_IO_PROTOCOL *This,
|
||
|
IN OUT UINTN *BufferSize,
|
||
|
OUT VOID *Buffer
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// Serial Driver Defaults
|
||
|
//
|
||
|
#define SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH 1
|
||
|
#define SERIAL_PORT_DEFAULT_TIMEOUT 1000000
|
||
|
#define SERIAL_PORT_DEFAULT_CONTROL_MASK 0
|
||
|
#define SERIAL_PORT_LOOPBACK_BUFFER_FULL BIT8
|
||
|
|
||
|
//
|
||
|
// EFI_SERIAL_IO_MODE instance
|
||
|
//
|
||
|
EFI_SERIAL_IO_MODE mSerialIoMode = {
|
||
|
SERIAL_PORT_DEFAULT_CONTROL_MASK,
|
||
|
SERIAL_PORT_DEFAULT_TIMEOUT,
|
||
|
0, // BaudRate
|
||
|
SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH,
|
||
|
0, // DataBits
|
||
|
0, // Parity
|
||
|
0 // StopBits
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// EFI_SERIAL_IO_PROTOCOL instance
|
||
|
//
|
||
|
EFI_SERIAL_IO_PROTOCOL mSerialIo = {
|
||
|
SERIAL_IO_INTERFACE_REVISION,
|
||
|
SerialReset,
|
||
|
SerialSetAttributes,
|
||
|
SerialSetControl,
|
||
|
SerialGetControl,
|
||
|
SerialWrite,
|
||
|
SerialRead,
|
||
|
&mSerialIoMode
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Serial IO Device Path definition
|
||
|
//
|
||
|
typedef struct {
|
||
|
VENDOR_DEVICE_PATH VendorDevicePath;
|
||
|
UART_DEVICE_PATH UartDevicePath;
|
||
|
EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
|
||
|
} SERIAL_IO_DEVICE_PATH;
|
||
|
|
||
|
//
|
||
|
// Serial IO Device Patch instance
|
||
|
//
|
||
|
SERIAL_IO_DEVICE_PATH mSerialIoDevicePath = {
|
||
|
{
|
||
|
{
|
||
|
HARDWARE_DEVICE_PATH,
|
||
|
HW_VENDOR_DP,
|
||
|
(UINT8) (sizeof (VENDOR_DEVICE_PATH)),
|
||
|
(UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
|
||
|
},
|
||
|
EFI_DEBUG_AGENT_GUID,
|
||
|
},
|
||
|
{
|
||
|
{
|
||
|
MESSAGING_DEVICE_PATH,
|
||
|
MSG_UART_DP,
|
||
|
(UINT8) (sizeof (UART_DEVICE_PATH)),
|
||
|
(UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8)
|
||
|
},
|
||
|
0,
|
||
|
0, // BaudRate
|
||
|
0, // DataBits
|
||
|
0, // Parity
|
||
|
0, // StopBits
|
||
|
},
|
||
|
{
|
||
|
END_DEVICE_PATH_TYPE,
|
||
|
END_ENTIRE_DEVICE_PATH_SUBTYPE,
|
||
|
{
|
||
|
END_DEVICE_PATH_LENGTH,
|
||
|
0
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
#define DEBGU_SERIAL_IO_FIFO_DEPTH 10
|
||
|
//
|
||
|
// Data buffer for Terminal input character and Debug Symbols.
|
||
|
// The depth is DEBGU_SERIAL_IO_FIFO_DEPTH.
|
||
|
// Fields:
|
||
|
// First UINT8: The index of the first data in array Data[].
|
||
|
// Last UINT8: The index, which you can put a new data into array Data[].
|
||
|
// Surplus UINT8: Identify how many data you can put into array Data[].
|
||
|
// Data[] UINT8: An array, which used to store data.
|
||
|
//
|
||
|
typedef struct {
|
||
|
UINT8 First;
|
||
|
UINT8 Last;
|
||
|
UINT8 Surplus;
|
||
|
UINT8 Data[DEBGU_SERIAL_IO_FIFO_DEPTH];
|
||
|
} DEBUG_SERIAL_FIFO;
|
||
|
|
||
|
//
|
||
|
// Global Varibles
|
||
|
//
|
||
|
EFI_HANDLE mSerialIoHandle = NULL;
|
||
|
UINTN mLoopbackBuffer = 0;
|
||
|
DEBUG_SERIAL_FIFO mSerialFifoForTerminal = {0, 0, DEBGU_SERIAL_IO_FIFO_DEPTH, { 0 }};
|
||
|
DEBUG_SERIAL_FIFO mSerialFifoForDebug = {0, 0, DEBGU_SERIAL_IO_FIFO_DEPTH, { 0 }};
|
||
|
|
||
|
/**
|
||
|
Detect whether specific FIFO is empty or not.
|
||
|
|
||
|
@param[in] Fifo A pointer to the Data Structure DEBUG_SERIAL_FIFO.
|
||
|
|
||
|
@return whether specific FIFO is empty or not.
|
||
|
|
||
|
**/
|
||
|
BOOLEAN
|
||
|
IsDebugTermianlFifoEmpty (
|
||
|
IN DEBUG_SERIAL_FIFO *Fifo
|
||
|
)
|
||
|
{
|
||
|
if (Fifo->Surplus == DEBGU_SERIAL_IO_FIFO_DEPTH) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Detect whether specific FIFO is full or not.
|
||
|
|
||
|
@param[in] Fifo A pointer to the Data Structure DEBUG_SERIAL_FIFO.
|
||
|
|
||
|
@return whether specific FIFO is full or not.
|
||
|
|
||
|
**/
|
||
|
BOOLEAN
|
||
|
IsDebugTerminalFifoFull (
|
||
|
IN DEBUG_SERIAL_FIFO *Fifo
|
||
|
)
|
||
|
|
||
|
{
|
||
|
if (Fifo->Surplus == 0) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Add data to specific FIFO.
|
||
|
|
||
|
@param[in] Fifo A pointer to the Data Structure DEBUG_SERIAL_FIFO.
|
||
|
@param[in] Data The data added to FIFO.
|
||
|
|
||
|
@retval EFI_SUCCESS Add data to specific FIFO successfully.
|
||
|
@retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
DebugTerminalFifoAdd (
|
||
|
IN DEBUG_SERIAL_FIFO *Fifo,
|
||
|
IN UINT8 Data
|
||
|
)
|
||
|
|
||
|
{
|
||
|
//
|
||
|
// if FIFO full can not add data
|
||
|
//
|
||
|
if (IsDebugTerminalFifoFull (Fifo)) {
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
//
|
||
|
// FIFO is not full can add data
|
||
|
//
|
||
|
Fifo->Data[Fifo->Last] = Data;
|
||
|
Fifo->Surplus--;
|
||
|
Fifo->Last++;
|
||
|
if (Fifo->Last == DEBGU_SERIAL_IO_FIFO_DEPTH) {
|
||
|
Fifo->Last = 0;
|
||
|
}
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Remove data from specific FIFO.
|
||
|
|
||
|
@param[in] Fifo A pointer to the Data Structure DEBUG_SERIAL_FIFO.
|
||
|
@param[out] Data The data removed from FIFO.
|
||
|
|
||
|
@retval EFI_SUCCESS Remove data from specific FIFO successfully.
|
||
|
@retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
DebugTerminalFifoRemove (
|
||
|
IN DEBUG_SERIAL_FIFO *Fifo,
|
||
|
OUT UINT8 *Data
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// if FIFO is empty, no data can remove
|
||
|
//
|
||
|
if (IsDebugTermianlFifoEmpty (Fifo)) {
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
//
|
||
|
// FIFO is not empty, can remove data
|
||
|
//
|
||
|
*Data = Fifo->Data[Fifo->First];
|
||
|
Fifo->Surplus++;
|
||
|
Fifo->First++;
|
||
|
if (Fifo->First == DEBGU_SERIAL_IO_FIFO_DEPTH) {
|
||
|
Fifo->First = 0;
|
||
|
}
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Notification function on EFI PCD protocol to install EFI Serial IO protocol based
|
||
|
on Debug Communication Library.
|
||
|
|
||
|
@param[in] Event The event of notify protocol.
|
||
|
@param[in] Context Notify event context.
|
||
|
|
||
|
**/
|
||
|
VOID
|
||
|
EFIAPI
|
||
|
InstallSerialIoNotification (
|
||
|
IN EFI_EVENT Event,
|
||
|
IN VOID *Context
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
|
||
|
//
|
||
|
// Get Debug Port parameters from PCDs
|
||
|
//
|
||
|
mSerialIoDevicePath.UartDevicePath.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
|
||
|
mSerialIoDevicePath.UartDevicePath.DataBits = PcdGet8 (PcdUartDefaultDataBits);
|
||
|
mSerialIoDevicePath.UartDevicePath.Parity = PcdGet8 (PcdUartDefaultParity);
|
||
|
mSerialIoDevicePath.UartDevicePath.StopBits = PcdGet8 (PcdUartDefaultStopBits);
|
||
|
|
||
|
mSerialIoMode.BaudRate = mSerialIoDevicePath.UartDevicePath.BaudRate;
|
||
|
mSerialIoMode.DataBits = mSerialIoDevicePath.UartDevicePath.DataBits;
|
||
|
mSerialIoMode.Parity = mSerialIoDevicePath.UartDevicePath.Parity;
|
||
|
mSerialIoMode.StopBits = mSerialIoDevicePath.UartDevicePath.StopBits;
|
||
|
|
||
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
||
|
&mSerialIoHandle,
|
||
|
&gEfiDevicePathProtocolGuid, &mSerialIoDevicePath,
|
||
|
&gEfiSerialIoProtocolGuid, &mSerialIo,
|
||
|
NULL
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
DEBUG ((EFI_D_ERROR, "Debug Agent: Failed to install EFI Serial IO Protocol on Debug Port!\n"));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Reset serial device.
|
||
|
|
||
|
@param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
|
||
|
|
||
|
@retval EFI_SUCCESS Reset successfully.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
SerialReset (
|
||
|
IN EFI_SERIAL_IO_PROTOCOL *This
|
||
|
)
|
||
|
{
|
||
|
mSerialIoMode.ControlMask = SERIAL_PORT_DEFAULT_CONTROL_MASK;
|
||
|
mLoopbackBuffer = 0;
|
||
|
//
|
||
|
// Not reset serial devcie hardware indeed.
|
||
|
//
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Set new attributes to a serial device.
|
||
|
|
||
|
@param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
|
||
|
@param[in] BaudRate The baudrate of the serial device.
|
||
|
@param[in] ReceiveFifoDepth The depth of receive FIFO buffer.
|
||
|
@param[in] Timeout The request timeout for a single char.
|
||
|
@param[in] Parity The type of parity used in serial device.
|
||
|
@param[in] DataBits Number of databits used in serial device.
|
||
|
@param[in] StopBits Number of stopbits used in serial device.
|
||
|
|
||
|
@retval EFI_SUCCESS The new attributes were set.
|
||
|
@retval EFI_INVALID_PARAMETER One or more attributes have an unsupported value.
|
||
|
@retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return).
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
SerialSetAttributes (
|
||
|
IN EFI_SERIAL_IO_PROTOCOL *This,
|
||
|
IN UINT64 BaudRate,
|
||
|
IN UINT32 ReceiveFifoDepth,
|
||
|
IN UINT32 Timeout,
|
||
|
IN EFI_PARITY_TYPE Parity,
|
||
|
IN UINT8 DataBits,
|
||
|
IN EFI_STOP_BITS_TYPE StopBits
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// The Debug Communication Library does not support changing communications parameters, so unless
|
||
|
// the request is to use the default value or the value the Debug Communication Library is already
|
||
|
// using, then return EFI_INVALID_PARAMETER.
|
||
|
//
|
||
|
if (BaudRate != 0 && BaudRate != PcdGet64 (PcdUartDefaultBaudRate)) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
if (Parity != DefaultParity && Parity != PcdGet8 (PcdUartDefaultParity)) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
if (DataBits != 0 && DataBits != PcdGet8 (PcdUartDefaultDataBits)) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
if (StopBits != DefaultStopBits && StopBits != PcdGet8 (PcdUartDefaultStopBits)) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Update the Timeout value in the mode structure based on the request.
|
||
|
// The Debug Communication Library can not support a timeout on writes, but the timeout on
|
||
|
// reads can be provided by this module.
|
||
|
//
|
||
|
if (Timeout == 0) {
|
||
|
mSerialIoMode.Timeout = SERIAL_PORT_DEFAULT_TIMEOUT;
|
||
|
} else {
|
||
|
mSerialIoMode.Timeout = Timeout;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Update the ReceiveFifoDepth value in the mode structure based on the request.
|
||
|
// This module assumes that the Debug Communication Library uses a FIFO depth of
|
||
|
// SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH. The Debug Communication Library may actually be
|
||
|
// using a larger FIFO, but there is no way to tell.
|
||
|
//
|
||
|
if (ReceiveFifoDepth == 0 || ReceiveFifoDepth >= SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH) {
|
||
|
mSerialIoMode.ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH;
|
||
|
} else {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Set Control Bits.
|
||
|
|
||
|
@param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
|
||
|
@param[in] Control Control bits that can be settable.
|
||
|
|
||
|
@retval EFI_SUCCESS New Control bits were set successfully.
|
||
|
@retval EFI_UNSUPPORTED The Control bits wanted to set are not supported.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
SerialSetControl (
|
||
|
IN EFI_SERIAL_IO_PROTOCOL *This,
|
||
|
IN UINT32 Control
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// The only control bit supported by this module is software loopback.
|
||
|
// If any other bit is set, then return an error
|
||
|
//
|
||
|
if ((Control & (~EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE)) != 0) {
|
||
|
return EFI_UNSUPPORTED;
|
||
|
}
|
||
|
mSerialIoMode.ControlMask = Control;
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Get ControlBits.
|
||
|
|
||
|
@param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
|
||
|
@param[out] Control Control signals of the serial device.
|
||
|
|
||
|
@retval EFI_SUCCESS Get Control signals successfully.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
SerialGetControl (
|
||
|
IN EFI_SERIAL_IO_PROTOCOL *This,
|
||
|
OUT UINT32 *Control
|
||
|
)
|
||
|
{
|
||
|
DEBUG_PORT_HANDLE Handle;
|
||
|
|
||
|
Handle = GetDebugPortHandle ();
|
||
|
|
||
|
//
|
||
|
// Always assume the output buffer is empty and the Debug Communication Library can process
|
||
|
// more write requests.
|
||
|
//
|
||
|
*Control = mSerialIoMode.ControlMask | EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
|
||
|
|
||
|
//
|
||
|
// Check to see if the Terminal FIFO is empty and
|
||
|
// check to see if the input buffer in the Debug Communication Library is empty
|
||
|
//
|
||
|
if (!IsDebugTermianlFifoEmpty (&mSerialFifoForTerminal) || DebugPortPollBuffer (Handle)) {
|
||
|
*Control &= ~EFI_SERIAL_INPUT_BUFFER_EMPTY;
|
||
|
}
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Write the specified number of bytes to serial device.
|
||
|
|
||
|
@param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
|
||
|
@param[in, out] BufferSize On input the size of Buffer, on output the amount of
|
||
|
data actually written.
|
||
|
@param[in] Buffer The buffer of data to write.
|
||
|
|
||
|
@retval EFI_SUCCESS The data were written successfully.
|
||
|
@retval EFI_DEVICE_ERROR The device reported an error.
|
||
|
@retval EFI_TIMEOUT The write operation was stopped due to timeout.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
SerialWrite (
|
||
|
IN EFI_SERIAL_IO_PROTOCOL *This,
|
||
|
IN OUT UINTN *BufferSize,
|
||
|
IN VOID *Buffer
|
||
|
)
|
||
|
{
|
||
|
DEBUG_PORT_HANDLE Handle;
|
||
|
|
||
|
Handle = GetDebugPortHandle ();
|
||
|
|
||
|
if ((mSerialIoMode.ControlMask & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) != 0) {
|
||
|
if (*BufferSize == 0) {
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
if ((mLoopbackBuffer & SERIAL_PORT_LOOPBACK_BUFFER_FULL) != 0) {
|
||
|
*BufferSize = 0;
|
||
|
return EFI_TIMEOUT;
|
||
|
}
|
||
|
mLoopbackBuffer = SERIAL_PORT_LOOPBACK_BUFFER_FULL | *(UINT8 *)Buffer;
|
||
|
*BufferSize = 1;
|
||
|
} else {
|
||
|
*BufferSize = DebugPortWriteBuffer (Handle, Buffer, *BufferSize);
|
||
|
}
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Read the specified number of bytes from serial device.
|
||
|
|
||
|
@param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
|
||
|
@param[in, out] BufferSize On input the size of Buffer, on output the amount of
|
||
|
data returned in buffer.
|
||
|
@param[out] Buffer The buffer to return the data into.
|
||
|
|
||
|
@retval EFI_SUCCESS The data were read successfully.
|
||
|
@retval EFI_DEVICE_ERROR The device reported an error.
|
||
|
@retval EFI_TIMEOUT The read operation was stopped due to timeout.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
SerialRead (
|
||
|
IN EFI_SERIAL_IO_PROTOCOL *This,
|
||
|
IN OUT UINTN *BufferSize,
|
||
|
OUT VOID *Buffer
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
UINTN Index;
|
||
|
UINT8 *Uint8Buffer;
|
||
|
BOOLEAN OldInterruptState;
|
||
|
DEBUG_PORT_HANDLE Handle;
|
||
|
UINT8 Data;
|
||
|
|
||
|
Handle = GetDebugPortHandle ();
|
||
|
|
||
|
//
|
||
|
// Save and disable Debug Timer interrupt to avoid it to access Debug Port
|
||
|
//
|
||
|
OldInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);
|
||
|
|
||
|
Uint8Buffer = (UINT8 *)Buffer;
|
||
|
if ((mSerialIoMode.ControlMask & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) != 0) {
|
||
|
if ((mLoopbackBuffer & SERIAL_PORT_LOOPBACK_BUFFER_FULL) == 0) {
|
||
|
return EFI_TIMEOUT;
|
||
|
}
|
||
|
*Uint8Buffer = (UINT8)(mLoopbackBuffer & 0xff);
|
||
|
mLoopbackBuffer = 0;
|
||
|
*BufferSize = 1;
|
||
|
} else {
|
||
|
for (Index = 0; Index < *BufferSize; Index++) {
|
||
|
//
|
||
|
// Read input character from terminal FIFO firstly
|
||
|
//
|
||
|
Status = DebugTerminalFifoRemove (&mSerialFifoForTerminal, &Data);
|
||
|
if (Status == EFI_SUCCESS) {
|
||
|
*Uint8Buffer = Data;
|
||
|
Uint8Buffer ++;
|
||
|
continue;
|
||
|
}
|
||
|
//
|
||
|
// Read the input character from Debug Port
|
||
|
//
|
||
|
if (!DebugPortPollBuffer (Handle)) {
|
||
|
break;
|
||
|
}
|
||
|
DebugPortReadBuffer (Handle, &Data, 1, 0);
|
||
|
|
||
|
if (Data== DEBUG_STARTING_SYMBOL_ATTACH ||
|
||
|
Data == DEBUG_STARTING_SYMBOL_BREAK) {
|
||
|
//
|
||
|
// Add the debug symbol into Debug FIFO
|
||
|
//
|
||
|
DebugTerminalFifoAdd (&mSerialFifoForDebug, Data);
|
||
|
} else {
|
||
|
*Uint8Buffer = Data;
|
||
|
Uint8Buffer ++;
|
||
|
}
|
||
|
}
|
||
|
*BufferSize = (UINTN)Uint8Buffer - (UINTN)Buffer;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Restore Debug Timer interrupt
|
||
|
//
|
||
|
SaveAndSetDebugTimerInterrupt (OldInterruptState);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Read the Attach/Break-in symbols from the debug port.
|
||
|
|
||
|
@param[in] Handle Pointer to Debug Port handle.
|
||
|
@param[out] BreakSymbol Returned break symbol.
|
||
|
|
||
|
@retval EFI_SUCCESS Read the symbol in BreakSymbol.
|
||
|
@retval EFI_NOT_FOUND No read the break symbol.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
DebugReadBreakSymbol (
|
||
|
IN DEBUG_PORT_HANDLE Handle,
|
||
|
OUT UINT8 *BreakSymbol
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
UINT8 Data;
|
||
|
|
||
|
Status = DebugTerminalFifoRemove (&mSerialFifoForDebug, &Data);
|
||
|
if (Status != EFI_SUCCESS) {
|
||
|
if (!DebugPortPollBuffer (Handle)) {
|
||
|
//
|
||
|
// No data in Debug Port buffer.
|
||
|
//
|
||
|
return EFI_NOT_FOUND;
|
||
|
} else {
|
||
|
//
|
||
|
// Read one character from Debug Port.
|
||
|
//
|
||
|
DebugPortReadBuffer (Handle, &Data, 1, 0);
|
||
|
if ((Data != DEBUG_STARTING_SYMBOL_ATTACH) && (Data != DEBUG_STARTING_SYMBOL_BREAK)) {
|
||
|
//
|
||
|
// If the data is not Break symbol, add it into Terminal FIFO
|
||
|
//
|
||
|
DebugTerminalFifoAdd (&mSerialFifoForTerminal, Data);
|
||
|
return EFI_NOT_FOUND;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*BreakSymbol = Data;
|
||
|
return EFI_SUCCESS;
|
||
|
}
|