summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/SerialIo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/SerialIo.c')
-rw-r--r--src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/SerialIo.c808
1 files changed, 808 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/SerialIo.c b/src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/SerialIo.c
new file mode 100644
index 00000000..b5176ac9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/SerialIo.c
@@ -0,0 +1,808 @@
+/** @file
+ Install Serial IO Protocol that layers on top of a Debug Communication Library instance.
+
+ Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "DxeDebugAgentLib.h"
+
+//
+// Serial I/O Protocol Interface definitions.
+//
+
+/**
+ 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, // default BaudRate
+ SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH,
+ 0, // default DataBits
+ 0, // default Parity
+ 0 // default 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, // default BaudRate
+ 0, // default DataBits
+ 0, // default Parity
+ 0, // default 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 Variables
+//
+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;
+}
+
+/**
+ Install EFI Serial IO protocol based on Debug Communication Library.
+
+**/
+VOID
+InstallSerialIo (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ 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 device 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 CAN NOT change communications parameters (if it has)
+ // actually. Because it also has no any idea on what parameters are based on, we cannot
+ // check the input parameters (like BaudRate, Parity, DataBits and StopBits).
+ //
+
+ //
+ // 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;
+ BOOLEAN DebugTimerInterruptState;
+ EFI_TPL Tpl;
+
+ //
+ // Raise TPL to prevent recursion from EFI timer interrupts
+ //
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ //
+ // Save and disable Debug Timer interrupt to avoid it to access Debug Port
+ //
+ DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);
+ 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;
+ }
+
+ //
+ // Restore Debug Timer interrupt
+ //
+ SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);
+
+ //
+ // Restore to original TPL
+ //
+ gBS->RestoreTPL (Tpl);
+
+ 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;
+ BOOLEAN DebugTimerInterruptState;
+ EFI_TPL Tpl;
+
+ //
+ // Raise TPL to prevent recursion from EFI timer interrupts
+ //
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ //
+ // Save and disable Debug Timer interrupt to avoid it to access Debug Port
+ //
+ DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);
+ 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);
+ }
+
+ //
+ // Restore Debug Timer interrupt
+ //
+ SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);
+
+ //
+ // Restore to original TPL
+ //
+ gBS->RestoreTPL (Tpl);
+
+ 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 DebugTimerInterruptState;
+ EFI_TPL Tpl;
+ DEBUG_PORT_HANDLE Handle;
+ DEBUG_PACKET_HEADER DebugHeader;
+ UINT8 *Data8;
+
+ //
+ // Raise TPL to prevent recursion from EFI timer interrupts
+ //
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ //
+ // Save and disable Debug Timer interrupt to avoid it to access Debug Port
+ //
+ DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);
+ Handle = GetDebugPortHandle ();
+
+ Data8 = (UINT8 *) &DebugHeader;
+ 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, Data8);
+ if (Status == EFI_SUCCESS) {
+ *Uint8Buffer = *Data8;
+ Uint8Buffer ++;
+ continue;
+ }
+ //
+ // Read the input character from Debug Port
+ //
+ if (!DebugPortPollBuffer (Handle)) {
+ break;
+ }
+ DebugAgentReadBuffer (Handle, Data8, 1, 0);
+
+ if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {
+ //
+ // Add the debug symbol into Debug FIFO
+ //
+ DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Terminal Timer attach symbol received %x", *Data8);
+ DebugTerminalFifoAdd (&mSerialFifoForDebug, *Data8);
+ } else if (*Data8 == DEBUG_STARTING_SYMBOL_NORMAL) {
+ Status = ReadRemainingBreakPacket (Handle, &DebugHeader);
+ if (Status == EFI_SUCCESS) {
+ DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Terminal Timer break symbol received %x", DebugHeader.Command);
+ DebugTerminalFifoAdd (&mSerialFifoForDebug, DebugHeader.Command);
+ }
+ if (Status == EFI_TIMEOUT) {
+ continue;
+ }
+ } else {
+ *Uint8Buffer = *Data8;
+ Uint8Buffer ++;
+ }
+ }
+ *BufferSize = (UINTN)Uint8Buffer - (UINTN)Buffer;
+ }
+
+ //
+ // Restore Debug Timer interrupt
+ //
+ SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);
+
+ //
+ // Restore to original TPL
+ //
+ gBS->RestoreTPL (Tpl);
+
+ 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
+DebugReadBreakFromDebugPort (
+ IN DEBUG_PORT_HANDLE Handle,
+ OUT UINT8 *BreakSymbol
+ )
+{
+ EFI_STATUS Status;
+ DEBUG_PACKET_HEADER DebugHeader;
+ UINT8 *Data8;
+
+ *BreakSymbol = 0;
+ //
+ // If Debug Port buffer has data, read it till it was break symbol or Debug Port buffer empty.
+ //
+ Data8 = (UINT8 *) &DebugHeader;
+ while (TRUE) {
+ //
+ // If start symbol is not received
+ //
+ if (!DebugPortPollBuffer (Handle)) {
+ //
+ // If no data in Debug Port, exit
+ //
+ break;
+ }
+ //
+ // Try to read the start symbol
+ //
+ DebugAgentReadBuffer (Handle, Data8, 1, 0);
+ if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {
+ DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer attach symbol received %x", *Data8);
+ *BreakSymbol = *Data8;
+ return EFI_SUCCESS;
+ }
+ if (*Data8 == DEBUG_STARTING_SYMBOL_NORMAL) {
+ Status = ReadRemainingBreakPacket (Handle, &DebugHeader);
+ if (Status == EFI_SUCCESS) {
+ DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer break symbol received %x", DebugHeader.Command);
+ *BreakSymbol = DebugHeader.Command;
+ return EFI_SUCCESS;
+ }
+ if (Status == EFI_TIMEOUT) {
+ break;
+ }
+ } else {
+ //
+ // Add to Terminal FIFO
+ //
+ DebugTerminalFifoAdd (&mSerialFifoForTerminal, *Data8);
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Read the Attach/Break-in symbols.
+
+ @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 Data8;
+
+ //
+ // Read break symbol from debug FIFO firstly
+ //
+ Status = DebugTerminalFifoRemove (&mSerialFifoForDebug, &Data8);
+ if (Status == EFI_SUCCESS) {
+ *BreakSymbol = Data8;
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Read Break symbol from debug port
+ //
+ return DebugReadBreakFromDebugPort (Handle, BreakSymbol);
+ }
+}