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