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