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 **/
29 EFI_STATUS
30 EFIAPI
31 SerialReset (
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 **/
51 EFI_STATUS
52 EFIAPI
53 SerialSetAttributes (
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 **/
73 EFI_STATUS
74 EFIAPI
75 SerialSetControl (
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 **/
89 EFI_STATUS
90 EFIAPI
91 SerialGetControl (
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 **/
109 EFI_STATUS
110 EFIAPI
111 SerialWrite (
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 **/
130 EFI_STATUS
131 EFIAPI
132 SerialRead (
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 //
149 EFI_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 //
162 EFI_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 //
176 typedef 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 //
185 SERIAL_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 //
232 typedef 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 //
242 EFI_HANDLE mSerialIoHandle = NULL;
243 UINTN mLoopbackBuffer = 0;
244 DEBUG_SERIAL_FIFO mSerialFifoForTerminal = {0, 0, DEBGU_SERIAL_IO_FIFO_DEPTH, { 0 }};
245 DEBUG_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 **/
255 BOOLEAN
IsDebugTermianlFifoEmpty(IN DEBUG_SERIAL_FIFO * Fifo)256 IsDebugTermianlFifoEmpty (
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 **/
275 BOOLEAN
IsDebugTerminalFifoFull(IN DEBUG_SERIAL_FIFO * Fifo)276 IsDebugTerminalFifoFull (
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 **/
298 EFI_STATUS
DebugTerminalFifoAdd(IN DEBUG_SERIAL_FIFO * Fifo,IN UINT8 Data)299 DebugTerminalFifoAdd (
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 **/
334 EFI_STATUS
DebugTerminalFifoRemove(IN DEBUG_SERIAL_FIFO * Fifo,OUT UINT8 * Data)335 DebugTerminalFifoRemove (
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 **/
363 VOID
InstallSerialIo(VOID)364 InstallSerialIo (
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 **/
389 EFI_STATUS
390 EFIAPI
SerialReset(IN EFI_SERIAL_IO_PROTOCOL * This)391 SerialReset (
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 **/
419 EFI_STATUS
420 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)421 SerialSetAttributes (
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 **/
473 EFI_STATUS
474 EFIAPI
SerialSetControl(IN EFI_SERIAL_IO_PROTOCOL * This,IN UINT32 Control)475 SerialSetControl (
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 **/
500 EFI_STATUS
501 EFIAPI
SerialGetControl(IN EFI_SERIAL_IO_PROTOCOL * This,OUT UINT32 * Control)502 SerialGetControl (
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 **/
562 EFI_STATUS
563 EFIAPI
SerialWrite(IN EFI_SERIAL_IO_PROTOCOL * This,IN OUT UINTN * BufferSize,IN VOID * Buffer)564 SerialWrite (
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 **/
625 EFI_STATUS
626 EFIAPI
SerialRead(IN EFI_SERIAL_IO_PROTOCOL * This,IN OUT UINTN * BufferSize,OUT VOID * Buffer)627 SerialRead (
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 **/
727 EFI_STATUS
DebugReadBreakFromDebugPort(IN DEBUG_PORT_HANDLE Handle,OUT UINT8 * BreakSymbol)728 DebugReadBreakFromDebugPort (
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 **/
792 EFI_STATUS
DebugReadBreakSymbol(IN DEBUG_PORT_HANDLE Handle,OUT UINT8 * BreakSymbol)793 DebugReadBreakSymbol (
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