1/** @file
2  Install Serial IO Protocol that layers on top of a Debug Communication Library instance.
3
4  Copyright (c) 2012 - 2015, Intel Corporation. All rights reserved.<BR>
5  This program and the accompanying materials
6  are licensed and made available under the terms and conditions of the BSD License
7  which accompanies this distribution.  The full text of the license may be found at
8  http://opensource.org/licenses/bsd-license.php.
9
10  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13**/
14
15#include "DxeDebugAgentLib.h"
16
17//
18// Serial I/O Protocol Interface defintions.
19//
20
21/**
22  Reset serial device.
23
24  @param[in] This           Pointer to EFI_SERIAL_IO_PROTOCOL.
25
26  @retval EFI_SUCCESS       Reset successfully.
27
28**/
29EFI_STATUS
30EFIAPI
31SerialReset (
32  IN EFI_SERIAL_IO_PROTOCOL  *This
33  );
34
35/**
36  Set new attributes to a serial device.
37
38  @param[in]  This                Pointer to EFI_SERIAL_IO_PROTOCOL.
39  @param[in]  BaudRate            The baudrate of the serial device.
40  @param[in]  ReceiveFifoDepth    The depth of receive FIFO buffer.
41  @param[in]  Timeout             The request timeout for a single char.
42  @param[in]  Parity              The type of parity used in serial device.
43  @param[in]  DataBits            Number of databits used in serial device.
44  @param[in]  StopBits            Number of stopbits used in serial device.
45
46  @retval EFI_SUCCESS             The new attributes were set.
47  @retval EFI_INVALID_PARAMETER   One or more attributes have an unsupported value.
48  @retval EFI_DEVICE_ERROR        The serial device is not functioning correctly (no return).
49
50**/
51EFI_STATUS
52EFIAPI
53SerialSetAttributes (
54  IN EFI_SERIAL_IO_PROTOCOL  *This,
55  IN UINT64                  BaudRate,
56  IN UINT32                  ReceiveFifoDepth,
57  IN UINT32                  Timeout,
58  IN EFI_PARITY_TYPE         Parity,
59  IN UINT8                   DataBits,
60  IN EFI_STOP_BITS_TYPE      StopBits
61  );
62
63/**
64  Set Control Bits.
65
66  @param[in] This            Pointer to EFI_SERIAL_IO_PROTOCOL.
67  @param[in] Control         Control bits that can be settable.
68
69  @retval EFI_SUCCESS        New Control bits were set successfully.
70  @retval EFI_UNSUPPORTED    The Control bits wanted to set are not supported.
71
72**/
73EFI_STATUS
74EFIAPI
75SerialSetControl (
76  IN EFI_SERIAL_IO_PROTOCOL  *This,
77  IN UINT32                  Control
78  );
79
80/**
81  Get ControlBits.
82
83  @param[in]  This         Pointer to EFI_SERIAL_IO_PROTOCOL.
84  @param[out] Control      Control signals of the serial device.
85
86  @retval EFI_SUCCESS  Get Control signals successfully.
87
88**/
89EFI_STATUS
90EFIAPI
91SerialGetControl (
92  IN EFI_SERIAL_IO_PROTOCOL  *This,
93  OUT UINT32                 *Control
94  );
95
96/**
97  Write the specified number of bytes to serial device.
98
99  @param[in]      This       Pointer to EFI_SERIAL_IO_PROTOCOL.
100  @param[in, out] BufferSize On input the size of Buffer, on output the amount of
101                             data actually written.
102  @param[in]      Buffer     The buffer of data to write.
103
104  @retval EFI_SUCCESS        The data were written successfully.
105  @retval EFI_DEVICE_ERROR   The device reported an error.
106  @retval EFI_TIMEOUT        The write operation was stopped due to timeout.
107
108**/
109EFI_STATUS
110EFIAPI
111SerialWrite (
112  IN EFI_SERIAL_IO_PROTOCOL  *This,
113  IN OUT UINTN               *BufferSize,
114  IN VOID                    *Buffer
115  );
116
117/**
118  Read the specified number of bytes from serial device.
119
120  @param[in] This            Pointer to EFI_SERIAL_IO_PROTOCOL.
121  @param[in, out] BufferSize On input the size of Buffer, on output the amount of
122                             data returned in buffer.
123  @param[out] Buffer         The buffer to return the data into.
124
125  @retval EFI_SUCCESS        The data were read successfully.
126  @retval EFI_DEVICE_ERROR   The device reported an error.
127  @retval EFI_TIMEOUT        The read operation was stopped due to timeout.
128
129**/
130EFI_STATUS
131EFIAPI
132SerialRead (
133  IN EFI_SERIAL_IO_PROTOCOL  *This,
134  IN OUT UINTN               *BufferSize,
135  OUT VOID                   *Buffer
136  );
137
138//
139// Serial Driver Defaults
140//
141#define SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH  1
142#define SERIAL_PORT_DEFAULT_TIMEOUT             1000000
143#define SERIAL_PORT_DEFAULT_CONTROL_MASK        0
144#define SERIAL_PORT_LOOPBACK_BUFFER_FULL        BIT8
145
146//
147// EFI_SERIAL_IO_MODE instance
148//
149EFI_SERIAL_IO_MODE  mSerialIoMode = {
150  SERIAL_PORT_DEFAULT_CONTROL_MASK,
151  SERIAL_PORT_DEFAULT_TIMEOUT,
152  0,  // default BaudRate
153  SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH,
154  0,  // default DataBits
155  0,  // default Parity
156  0   // default StopBits
157};
158
159//
160// EFI_SERIAL_IO_PROTOCOL instance
161//
162EFI_SERIAL_IO_PROTOCOL mSerialIo = {
163  SERIAL_IO_INTERFACE_REVISION,
164  SerialReset,
165  SerialSetAttributes,
166  SerialSetControl,
167  SerialGetControl,
168  SerialWrite,
169  SerialRead,
170  &mSerialIoMode
171};
172
173//
174// Serial IO Device Path definition
175//
176typedef struct {
177  VENDOR_DEVICE_PATH        VendorDevicePath;
178  UART_DEVICE_PATH          UartDevicePath;
179  EFI_DEVICE_PATH_PROTOCOL  EndDevicePath;
180} SERIAL_IO_DEVICE_PATH;
181
182//
183// Serial IO Device Patch instance
184//
185SERIAL_IO_DEVICE_PATH mSerialIoDevicePath = {
186  {
187    {
188      HARDWARE_DEVICE_PATH,
189      HW_VENDOR_DP,
190      {
191        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
192        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
193      }
194    },
195    EFI_DEBUG_AGENT_GUID,
196  },
197  {
198    {
199      MESSAGING_DEVICE_PATH,
200      MSG_UART_DP,
201      {
202        (UINT8) (sizeof (UART_DEVICE_PATH)),
203        (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8)
204      }
205    },
206    0,
207    0,  // default BaudRate
208    0,  // default DataBits
209    0,  // default Parity
210    0,  // default StopBits
211  },
212  {
213    END_DEVICE_PATH_TYPE,
214    END_ENTIRE_DEVICE_PATH_SUBTYPE,
215    {
216      END_DEVICE_PATH_LENGTH,
217      0
218    }
219  }
220};
221
222#define DEBGU_SERIAL_IO_FIFO_DEPTH      10
223//
224//  Data buffer for Terminal input character and Debug Symbols.
225//  The depth is DEBGU_SERIAL_IO_FIFO_DEPTH.
226//  Fields:
227//      First   UINT8: The index of the first data in array Data[].
228//      Last    UINT8: The index, which you can put a new data into array Data[].
229//      Surplus UINT8: Identify how many data you can put into array Data[].
230//      Data[]  UINT8: An array, which used to store data.
231//
232typedef struct {
233  UINT8  First;
234  UINT8  Last;
235  UINT8  Surplus;
236  UINT8  Data[DEBGU_SERIAL_IO_FIFO_DEPTH];
237} DEBUG_SERIAL_FIFO;
238
239//
240// Global Varibles
241//
242EFI_HANDLE                   mSerialIoHandle        = NULL;
243UINTN                        mLoopbackBuffer        = 0;
244DEBUG_SERIAL_FIFO            mSerialFifoForTerminal = {0, 0, DEBGU_SERIAL_IO_FIFO_DEPTH, { 0 }};
245DEBUG_SERIAL_FIFO            mSerialFifoForDebug    = {0, 0, DEBGU_SERIAL_IO_FIFO_DEPTH, { 0 }};
246
247/**
248  Detect whether specific FIFO is empty or not.
249
250  @param[in]  Fifo    A pointer to the Data Structure DEBUG_SERIAL_FIFO.
251
252  @return whether specific FIFO is empty or not.
253
254**/
255BOOLEAN
256IsDebugTermianlFifoEmpty (
257  IN DEBUG_SERIAL_FIFO    *Fifo
258  )
259{
260  if (Fifo->Surplus == DEBGU_SERIAL_IO_FIFO_DEPTH) {
261    return TRUE;
262  }
263
264  return FALSE;
265}
266
267/**
268  Detect whether specific FIFO is full or not.
269
270  @param[in] Fifo    A pointer to the Data Structure DEBUG_SERIAL_FIFO.
271
272  @return whether specific FIFO is full or not.
273
274**/
275BOOLEAN
276IsDebugTerminalFifoFull (
277  IN DEBUG_SERIAL_FIFO    *Fifo
278  )
279
280{
281  if (Fifo->Surplus == 0) {
282    return TRUE;
283  }
284
285  return FALSE;
286}
287
288/**
289  Add data to specific FIFO.
290
291  @param[in] Fifo               A pointer to the Data Structure DEBUG_SERIAL_FIFO.
292  @param[in] Data               The data added to FIFO.
293
294  @retval EFI_SUCCESS           Add data to specific FIFO successfully.
295  @retval EFI_OUT_OF_RESOURCE   Failed to add data because FIFO is already full.
296
297**/
298EFI_STATUS
299DebugTerminalFifoAdd (
300  IN DEBUG_SERIAL_FIFO   *Fifo,
301  IN UINT8               Data
302  )
303
304{
305  //
306  // if FIFO full can not add data
307  //
308  if (IsDebugTerminalFifoFull (Fifo)) {
309    return EFI_OUT_OF_RESOURCES;
310  }
311  //
312  // FIFO is not full can add data
313  //
314  Fifo->Data[Fifo->Last] = Data;
315  Fifo->Surplus--;
316  Fifo->Last++;
317  if (Fifo->Last == DEBGU_SERIAL_IO_FIFO_DEPTH) {
318    Fifo->Last = 0;
319  }
320
321  return EFI_SUCCESS;
322}
323
324/**
325  Remove data from specific FIFO.
326
327  @param[in]  Fifo              A pointer to the Data Structure DEBUG_SERIAL_FIFO.
328  @param[out] Data              The data removed from FIFO.
329
330  @retval EFI_SUCCESS           Remove data from specific FIFO successfully.
331  @retval EFI_OUT_OF_RESOURCE   Failed to remove data because FIFO is empty.
332
333**/
334EFI_STATUS
335DebugTerminalFifoRemove (
336  IN  DEBUG_SERIAL_FIFO   *Fifo,
337  OUT UINT8               *Data
338  )
339{
340  //
341  // if FIFO is empty, no data can remove
342  //
343  if (IsDebugTermianlFifoEmpty (Fifo)) {
344    return EFI_OUT_OF_RESOURCES;
345  }
346  //
347  // FIFO is not empty, can remove data
348  //
349  *Data = Fifo->Data[Fifo->First];
350  Fifo->Surplus++;
351  Fifo->First++;
352  if (Fifo->First == DEBGU_SERIAL_IO_FIFO_DEPTH) {
353    Fifo->First = 0;
354  }
355
356  return EFI_SUCCESS;
357}
358
359/**
360  Install EFI Serial IO protocol based on Debug Communication Library.
361
362**/
363VOID
364InstallSerialIo (
365  VOID
366  )
367{
368  EFI_STATUS       Status;
369
370  Status = gBS->InstallMultipleProtocolInterfaces (
371                  &mSerialIoHandle,
372                  &gEfiDevicePathProtocolGuid, &mSerialIoDevicePath,
373                  &gEfiSerialIoProtocolGuid,   &mSerialIo,
374                  NULL
375                  );
376  if (EFI_ERROR (Status)) {
377    DEBUG ((EFI_D_ERROR, "Debug Agent: Failed to install EFI Serial IO Protocol on Debug Port!\n"));
378  }
379}
380
381/**
382  Reset serial device.
383
384  @param[in] This           Pointer to EFI_SERIAL_IO_PROTOCOL.
385
386  @retval EFI_SUCCESS       Reset successfully.
387
388**/
389EFI_STATUS
390EFIAPI
391SerialReset (
392  IN EFI_SERIAL_IO_PROTOCOL  *This
393  )
394{
395  mSerialIoMode.ControlMask = SERIAL_PORT_DEFAULT_CONTROL_MASK;
396  mLoopbackBuffer = 0;
397  //
398  // Not reset serial devcie hardware indeed.
399  //
400  return EFI_SUCCESS;
401}
402
403/**
404  Set new attributes to a serial device.
405
406  @param[in]  This                Pointer to EFI_SERIAL_IO_PROTOCOL.
407  @param[in]  BaudRate            The baudrate of the serial device.
408  @param[in]  ReceiveFifoDepth    The depth of receive FIFO buffer.
409  @param[in]  Timeout             The request timeout for a single char.
410  @param[in]  Parity              The type of parity used in serial device.
411  @param[in]  DataBits            Number of databits used in serial device.
412  @param[in]  StopBits            Number of stopbits used in serial device.
413
414  @retval EFI_SUCCESS             The new attributes were set.
415  @retval EFI_INVALID_PARAMETER   One or more attributes have an unsupported value.
416  @retval EFI_DEVICE_ERROR        The serial device is not functioning correctly (no return).
417
418**/
419EFI_STATUS
420EFIAPI
421SerialSetAttributes (
422  IN EFI_SERIAL_IO_PROTOCOL  *This,
423  IN UINT64                  BaudRate,
424  IN UINT32                  ReceiveFifoDepth,
425  IN UINT32                  Timeout,
426  IN EFI_PARITY_TYPE         Parity,
427  IN UINT8                   DataBits,
428  IN EFI_STOP_BITS_TYPE      StopBits
429  )
430{
431  //
432  // The Debug Communication Library CAN NOT change communications parameters (if it has)
433  // actually. Because it also has no any idea on what parameters are based on, we cannot
434  // check the input parameters (like BaudRate, Parity, DataBits and StopBits).
435  //
436
437  //
438  // Update the Timeout value in the mode structure based on the request.
439  // The Debug Communication Library can not support a timeout on writes, but the timeout on
440  // reads can be provided by this module.
441  //
442  if (Timeout == 0) {
443    mSerialIoMode.Timeout = SERIAL_PORT_DEFAULT_TIMEOUT;
444  } else {
445    mSerialIoMode.Timeout = Timeout;
446  }
447
448  //
449  // Update the ReceiveFifoDepth value in the mode structure based on the request.
450  // This module assumes that the Debug Communication Library uses a FIFO depth of
451  // SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH.  The Debug Communication Library may actually be
452  // using a larger FIFO, but there is no way to tell.
453  //
454  if (ReceiveFifoDepth == 0 || ReceiveFifoDepth >= SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH) {
455    mSerialIoMode.ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH;
456  } else {
457    return EFI_INVALID_PARAMETER;
458  }
459
460  return EFI_SUCCESS;
461}
462
463/**
464  Set Control Bits.
465
466  @param[in] This            Pointer to EFI_SERIAL_IO_PROTOCOL.
467  @param[in] Control         Control bits that can be settable.
468
469  @retval EFI_SUCCESS        New Control bits were set successfully.
470  @retval EFI_UNSUPPORTED    The Control bits wanted to set are not supported.
471
472**/
473EFI_STATUS
474EFIAPI
475SerialSetControl (
476  IN EFI_SERIAL_IO_PROTOCOL  *This,
477  IN UINT32                  Control
478  )
479{
480  //
481  // The only control bit supported by this module is software loopback.
482  // If any other bit is set, then return an error
483  //
484  if ((Control & (~EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE)) != 0) {
485    return EFI_UNSUPPORTED;
486  }
487  mSerialIoMode.ControlMask = Control;
488  return EFI_SUCCESS;
489}
490
491/**
492  Get ControlBits.
493
494  @param[in]  This         Pointer to EFI_SERIAL_IO_PROTOCOL.
495  @param[out] Control      Control signals of the serial device.
496
497  @retval EFI_SUCCESS  Get Control signals successfully.
498
499**/
500EFI_STATUS
501EFIAPI
502SerialGetControl (
503  IN EFI_SERIAL_IO_PROTOCOL  *This,
504  OUT UINT32                 *Control
505  )
506{
507  DEBUG_PORT_HANDLE                Handle;
508  BOOLEAN                          DebugTimerInterruptState;
509  EFI_TPL                          Tpl;
510
511  //
512  // Raise TPL to prevent recursion from EFI timer interrupts
513  //
514  Tpl = gBS->RaiseTPL (TPL_NOTIFY);
515
516  //
517  // Save and disable Debug Timer interrupt to avoid it to access Debug Port
518  //
519  DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);
520  Handle = GetDebugPortHandle ();
521
522  //
523  // Always assume the output buffer is empty and the Debug Communication Library can process
524  // more write requests.
525  //
526  *Control = mSerialIoMode.ControlMask | EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
527
528  //
529  // Check to see if the Terminal FIFO is empty and
530  // check to see if the input buffer in the Debug Communication Library is empty
531  //
532  if (!IsDebugTermianlFifoEmpty (&mSerialFifoForTerminal) || DebugPortPollBuffer (Handle)) {
533    *Control &= ~EFI_SERIAL_INPUT_BUFFER_EMPTY;
534  }
535
536  //
537  // Restore Debug Timer interrupt
538  //
539  SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);
540
541  //
542  // Restore to original TPL
543  //
544  gBS->RestoreTPL (Tpl);
545
546  return EFI_SUCCESS;
547}
548
549/**
550  Write the specified number of bytes to serial device.
551
552  @param[in]      This       Pointer to EFI_SERIAL_IO_PROTOCOL.
553  @param[in, out] BufferSize On input the size of Buffer, on output the amount of
554                             data actually written.
555  @param[in]      Buffer     The buffer of data to write.
556
557  @retval EFI_SUCCESS        The data were written successfully.
558  @retval EFI_DEVICE_ERROR   The device reported an error.
559  @retval EFI_TIMEOUT        The write operation was stopped due to timeout.
560
561**/
562EFI_STATUS
563EFIAPI
564SerialWrite (
565  IN EFI_SERIAL_IO_PROTOCOL  *This,
566  IN OUT UINTN               *BufferSize,
567  IN VOID                    *Buffer
568  )
569{
570  DEBUG_PORT_HANDLE                Handle;
571  BOOLEAN                          DebugTimerInterruptState;
572  EFI_TPL                          Tpl;
573
574  //
575  // Raise TPL to prevent recursion from EFI timer interrupts
576  //
577  Tpl = gBS->RaiseTPL (TPL_NOTIFY);
578
579  //
580  // Save and disable Debug Timer interrupt to avoid it to access Debug Port
581  //
582  DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);
583  Handle = GetDebugPortHandle ();
584
585  if ((mSerialIoMode.ControlMask & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) != 0)  {
586    if (*BufferSize == 0) {
587      return EFI_SUCCESS;
588    }
589    if ((mLoopbackBuffer & SERIAL_PORT_LOOPBACK_BUFFER_FULL) != 0) {
590      *BufferSize = 0;
591      return EFI_TIMEOUT;
592    }
593    mLoopbackBuffer = SERIAL_PORT_LOOPBACK_BUFFER_FULL | *(UINT8 *)Buffer;
594    *BufferSize = 1;
595  } else {
596    *BufferSize = DebugPortWriteBuffer (Handle, Buffer, *BufferSize);
597  }
598
599  //
600  // Restore Debug Timer interrupt
601  //
602  SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);
603
604  //
605  // Restore to original TPL
606  //
607  gBS->RestoreTPL (Tpl);
608
609  return EFI_SUCCESS;
610}
611
612/**
613  Read the specified number of bytes from serial device.
614
615  @param[in] This            Pointer to EFI_SERIAL_IO_PROTOCOL.
616  @param[in, out] BufferSize On input the size of Buffer, on output the amount of
617                             data returned in buffer.
618  @param[out] Buffer         The buffer to return the data into.
619
620  @retval EFI_SUCCESS        The data were read successfully.
621  @retval EFI_DEVICE_ERROR   The device reported an error.
622  @retval EFI_TIMEOUT        The read operation was stopped due to timeout.
623
624**/
625EFI_STATUS
626EFIAPI
627SerialRead (
628  IN EFI_SERIAL_IO_PROTOCOL  *This,
629  IN OUT UINTN               *BufferSize,
630  OUT VOID                   *Buffer
631  )
632{
633  EFI_STATUS                  Status;
634  UINTN                       Index;
635  UINT8                       *Uint8Buffer;
636  BOOLEAN                     DebugTimerInterruptState;
637  EFI_TPL                     Tpl;
638  DEBUG_PORT_HANDLE           Handle;
639  DEBUG_PACKET_HEADER         DebugHeader;
640  UINT8                       *Data8;
641
642  //
643  // Raise TPL to prevent recursion from EFI timer interrupts
644  //
645  Tpl = gBS->RaiseTPL (TPL_NOTIFY);
646
647  //
648  // Save and disable Debug Timer interrupt to avoid it to access Debug Port
649  //
650  DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);
651  Handle = GetDebugPortHandle ();
652
653  Data8 = (UINT8 *) &DebugHeader;
654  Uint8Buffer = (UINT8 *)Buffer;
655  if ((mSerialIoMode.ControlMask & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) != 0)  {
656    if ((mLoopbackBuffer & SERIAL_PORT_LOOPBACK_BUFFER_FULL) == 0) {
657      return EFI_TIMEOUT;
658    }
659    *Uint8Buffer = (UINT8)(mLoopbackBuffer & 0xff);
660    mLoopbackBuffer = 0;
661    *BufferSize = 1;
662  } else {
663    for (Index = 0; Index < *BufferSize; Index++) {
664      //
665      // Read input character from terminal FIFO firstly
666      //
667      Status = DebugTerminalFifoRemove (&mSerialFifoForTerminal, Data8);
668      if (Status == EFI_SUCCESS) {
669        *Uint8Buffer = *Data8;
670        Uint8Buffer ++;
671        continue;
672      }
673      //
674      // Read the input character from Debug Port
675      //
676      if (!DebugPortPollBuffer (Handle)) {
677        break;
678      }
679      DebugAgentReadBuffer (Handle, Data8, 1, 0);
680
681      if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {
682        //
683        // Add the debug symbol into Debug FIFO
684        //
685        DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Terminal Timer attach symbol received %x", *Data8);
686        DebugTerminalFifoAdd (&mSerialFifoForDebug, *Data8);
687      } else if (*Data8 == DEBUG_STARTING_SYMBOL_NORMAL) {
688        Status = ReadRemainingBreakPacket (Handle, &DebugHeader);
689        if (Status == EFI_SUCCESS) {
690          DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Terminal Timer break symbol received %x", DebugHeader.Command);
691          DebugTerminalFifoAdd (&mSerialFifoForDebug, DebugHeader.Command);
692        }
693        if (Status == EFI_TIMEOUT) {
694          continue;
695        }
696      } else {
697        *Uint8Buffer = *Data8;
698        Uint8Buffer ++;
699      }
700    }
701    *BufferSize = (UINTN)Uint8Buffer - (UINTN)Buffer;
702  }
703
704  //
705  // Restore Debug Timer interrupt
706  //
707  SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);
708
709  //
710  // Restore to original TPL
711  //
712  gBS->RestoreTPL (Tpl);
713
714  return EFI_SUCCESS;
715}
716
717/**
718  Read the Attach/Break-in symbols from the debug port.
719
720  @param[in]  Handle         Pointer to Debug Port handle.
721  @param[out] BreakSymbol    Returned break symbol.
722
723  @retval EFI_SUCCESS        Read the symbol in BreakSymbol.
724  @retval EFI_NOT_FOUND      No read the break symbol.
725
726**/
727EFI_STATUS
728DebugReadBreakFromDebugPort (
729  IN  DEBUG_PORT_HANDLE      Handle,
730  OUT UINT8                  *BreakSymbol
731  )
732{
733  EFI_STATUS                 Status;
734  DEBUG_PACKET_HEADER        DebugHeader;
735  UINT8                      *Data8;
736
737  *BreakSymbol = 0;
738  //
739  // If Debug Port buffer has data, read it till it was break symbol or Debug Port buffer empty.
740  //
741  Data8 = (UINT8 *) &DebugHeader;
742  while (TRUE) {
743    //
744    // If start symbol is not received
745    //
746    if (!DebugPortPollBuffer (Handle)) {
747      //
748      // If no data in Debug Port, exit
749      //
750      break;
751    }
752    //
753    // Try to read the start symbol
754    //
755    DebugAgentReadBuffer (Handle, Data8, 1, 0);
756    if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {
757      DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer attach symbol received %x", *Data8);
758      *BreakSymbol = *Data8;
759      return EFI_SUCCESS;
760    }
761    if (*Data8 == DEBUG_STARTING_SYMBOL_NORMAL) {
762      Status = ReadRemainingBreakPacket (Handle, &DebugHeader);
763      if (Status == EFI_SUCCESS) {
764        DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer break symbol received %x", DebugHeader.Command);
765        *BreakSymbol = DebugHeader.Command;
766        return EFI_SUCCESS;
767      }
768      if (Status == EFI_TIMEOUT) {
769        break;
770      }
771    } else {
772      //
773      // Add to Terminal FIFO
774      //
775      DebugTerminalFifoAdd (&mSerialFifoForTerminal, *Data8);
776    }
777  }
778
779  return EFI_NOT_FOUND;
780}
781
782/**
783  Read the Attach/Break-in symbols.
784
785  @param[in]  Handle         Pointer to Debug Port handle.
786  @param[out] BreakSymbol    Returned break symbol.
787
788  @retval EFI_SUCCESS        Read the symbol in BreakSymbol.
789  @retval EFI_NOT_FOUND      No read the break symbol.
790
791**/
792EFI_STATUS
793DebugReadBreakSymbol (
794  IN  DEBUG_PORT_HANDLE      Handle,
795  OUT UINT8                  *BreakSymbol
796  )
797{
798  EFI_STATUS               Status;
799  UINT8                    Data8;
800
801  //
802  // Read break symbol from debug FIFO firstly
803  //
804  Status = DebugTerminalFifoRemove (&mSerialFifoForDebug, &Data8);
805  if (Status == EFI_SUCCESS) {
806    *BreakSymbol = Data8;
807    return EFI_SUCCESS;
808  } else {
809    //
810    // Read Break symbol from debug port
811    //
812    return DebugReadBreakFromDebugPort (Handle, BreakSymbol);
813  }
814}
815