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 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 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 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 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 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 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 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 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 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 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 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 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 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