1 /** @file 2 Commond Debug Agent library implementition. It mainly includes 3 the first C function called by exception/interrupt handlers, 4 read/write debug packet to communication with HOST based on transfer 5 protocol. 6 7 Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR> 8 This program and the accompanying materials 9 are licensed and made available under the terms and conditions of the BSD License 10 which accompanies this distribution. The full text of the license may be found at 11 http://opensource.org/licenses/bsd-license.php. 12 13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 15 16 **/ 17 18 #include "DebugAgent.h" 19 #include "Ia32/DebugException.h" 20 21 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgVersionAlert[] = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n"; 22 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgSendInitPacket[] = "\rSend INIT break packet and try to connect the HOST (Intel(R) UDK Debugger Tool v1.5) ...\r\n"; 23 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectOK[] = "HOST connection is successful!\r\n"; 24 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectFail[] = "HOST connection is failed!\r\n"; 25 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mWarningMsgIngoreBreakpoint[] = "Ignore break point in SMM for SMI issued during DXE debugging!\r\n"; 26 27 // 28 // Vector Handoff Info list used by Debug Agent for persist 29 // 30 GLOBAL_REMOVE_IF_UNREFERENCED EFI_VECTOR_HANDOFF_INFO mVectorHandoffInfoDebugAgent[] = { 31 { 32 DEBUG_EXCEPT_DIVIDE_ERROR, // Vector 0 33 EFI_VECTOR_HANDOFF_HOOK_BEFORE, 34 EFI_DEBUG_AGENT_GUID 35 }, 36 { 37 DEBUG_EXCEPT_DEBUG, // Vector 1 38 EFI_VECTOR_HANDOFF_DO_NOT_HOOK, 39 EFI_DEBUG_AGENT_GUID 40 }, 41 { 42 DEBUG_EXCEPT_NMI, // Vector 2 43 EFI_VECTOR_HANDOFF_HOOK_BEFORE, 44 EFI_DEBUG_AGENT_GUID 45 }, 46 { 47 DEBUG_EXCEPT_BREAKPOINT, // Vector 3 48 EFI_VECTOR_HANDOFF_DO_NOT_HOOK, 49 EFI_DEBUG_AGENT_GUID 50 }, 51 { 52 DEBUG_EXCEPT_OVERFLOW, // Vector 4 53 EFI_VECTOR_HANDOFF_HOOK_BEFORE, 54 EFI_DEBUG_AGENT_GUID 55 }, 56 { 57 DEBUG_EXCEPT_BOUND, // Vector 5 58 EFI_VECTOR_HANDOFF_HOOK_BEFORE, 59 EFI_DEBUG_AGENT_GUID 60 }, 61 { 62 DEBUG_EXCEPT_INVALID_OPCODE, // Vector 6 63 EFI_VECTOR_HANDOFF_HOOK_BEFORE, 64 EFI_DEBUG_AGENT_GUID 65 }, 66 { 67 DEBUG_EXCEPT_DOUBLE_FAULT, // Vector 8 68 EFI_VECTOR_HANDOFF_HOOK_BEFORE, 69 EFI_DEBUG_AGENT_GUID 70 }, 71 { 72 DEBUG_EXCEPT_INVALID_TSS, // Vector 10 73 EFI_VECTOR_HANDOFF_HOOK_BEFORE, 74 EFI_DEBUG_AGENT_GUID 75 }, 76 { 77 DEBUG_EXCEPT_SEG_NOT_PRESENT, // Vector 11 78 EFI_VECTOR_HANDOFF_HOOK_BEFORE, 79 EFI_DEBUG_AGENT_GUID 80 }, 81 { 82 DEBUG_EXCEPT_STACK_FAULT, // Vector 12 83 EFI_VECTOR_HANDOFF_HOOK_BEFORE, 84 EFI_DEBUG_AGENT_GUID 85 }, 86 { 87 DEBUG_EXCEPT_GP_FAULT, // Vector 13 88 EFI_VECTOR_HANDOFF_HOOK_BEFORE, 89 EFI_DEBUG_AGENT_GUID 90 }, 91 { 92 DEBUG_EXCEPT_PAGE_FAULT, // Vector 14 93 EFI_VECTOR_HANDOFF_HOOK_BEFORE, 94 EFI_DEBUG_AGENT_GUID 95 }, 96 { 97 DEBUG_EXCEPT_FP_ERROR, // Vector 16 98 EFI_VECTOR_HANDOFF_HOOK_BEFORE, 99 EFI_DEBUG_AGENT_GUID 100 }, 101 { 102 DEBUG_EXCEPT_ALIGNMENT_CHECK, // Vector 17 103 EFI_VECTOR_HANDOFF_HOOK_BEFORE, 104 EFI_DEBUG_AGENT_GUID 105 }, 106 { 107 DEBUG_EXCEPT_MACHINE_CHECK, // Vector 18 108 EFI_VECTOR_HANDOFF_HOOK_BEFORE, 109 EFI_DEBUG_AGENT_GUID 110 }, 111 { 112 DEBUG_EXCEPT_SIMD, // Vector 19 113 EFI_VECTOR_HANDOFF_HOOK_BEFORE, 114 EFI_DEBUG_AGENT_GUID 115 }, 116 { 117 DEBUG_TIMER_VECTOR, // Vector 32 118 EFI_VECTOR_HANDOFF_DO_NOT_HOOK, 119 EFI_DEBUG_AGENT_GUID 120 }, 121 { 122 DEBUG_MAILBOX_VECTOR, // Vector 33 123 EFI_VECTOR_HANDOFF_DO_NOT_HOOK, 124 EFI_DEBUG_AGENT_GUID 125 }, 126 { 127 0, 128 EFI_VECTOR_HANDOFF_LAST_ENTRY, 129 { 0 } 130 } 131 }; 132 133 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mVectorHandoffInfoCount = sizeof (mVectorHandoffInfoDebugAgent) / sizeof (EFI_VECTOR_HANDOFF_INFO); 134 135 /** 136 Calculate CRC16 for target data. 137 138 @param[in] Data The target data. 139 @param[in] DataSize The target data size. 140 @param[in] Crc Initial CRC. 141 142 @return UINT16 The CRC16 value. 143 144 **/ 145 UINT16 146 CalculateCrc16 ( 147 IN UINT8 *Data, 148 IN UINTN DataSize, 149 IN UINT16 Crc 150 ) 151 { 152 UINTN Index; 153 UINTN BitIndex; 154 155 for (Index = 0; Index < DataSize; Index++) { 156 Crc ^= (UINT16)Data[Index]; 157 for (BitIndex = 0; BitIndex < 8; BitIndex++) { 158 if ((Crc & 0x8000) != 0) { 159 Crc <<= 1; 160 Crc ^= 0x1021; 161 } else { 162 Crc <<= 1; 163 } 164 } 165 } 166 return Crc; 167 } 168 169 170 /** 171 Read IDT entry to check if IDT entries are setup by Debug Agent. 172 173 @retval TRUE IDT entries were setup by Debug Agent. 174 @retval FALSE IDT entries were not setup by Debug Agent. 175 176 **/ 177 BOOLEAN 178 IsDebugAgentInitialzed ( 179 VOID 180 ) 181 { 182 UINTN InterruptHandler; 183 184 InterruptHandler = (UINTN) GetExceptionHandlerInIdtEntry (0); 185 if (InterruptHandler >= 4 && *(UINT32 *)(InterruptHandler - 4) == AGENT_HANDLER_SIGNATURE) { 186 return TRUE; 187 } else { 188 return FALSE; 189 } 190 } 191 192 /** 193 Find and report module image info to HOST. 194 195 @param[in] AlignSize Image aligned size. 196 197 **/ 198 VOID 199 FindAndReportModuleImageInfo ( 200 IN UINTN AlignSize 201 ) 202 { 203 UINTN Pe32Data; 204 EFI_IMAGE_DOS_HEADER *DosHdr; 205 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; 206 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; 207 208 // 209 // Find Image Base 210 // 211 Pe32Data = ((UINTN)mErrorMsgVersionAlert) & ~(AlignSize - 1); 212 while (Pe32Data != 0) { 213 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data; 214 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { 215 // 216 // DOS image header is present, so read the PE header after the DOS image header. 217 // 218 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); 219 // 220 // Make sure PE header address does not overflow and is less than the initial address. 221 // 222 if (((UINTN)Hdr.Pe32 > Pe32Data) && ((UINTN)Hdr.Pe32 < (UINTN)mErrorMsgVersionAlert)) { 223 if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { 224 // 225 // It's PE image. 226 // 227 break; 228 } 229 } 230 } else { 231 // 232 // DOS image header is not present, TE header is at the image base. 233 // 234 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data; 235 if ((Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) && 236 ((Hdr.Te->Machine == IMAGE_FILE_MACHINE_I386) || Hdr.Te->Machine == IMAGE_FILE_MACHINE_X64)) { 237 // 238 // It's TE image, it TE header and Machine type match 239 // 240 break; 241 } 242 } 243 244 // 245 // Not found the image base, check the previous aligned address 246 // 247 Pe32Data -= AlignSize; 248 } 249 250 ImageContext.ImageAddress = Pe32Data; 251 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress); 252 PeCoffLoaderRelocateImageExtraAction (&ImageContext); 253 } 254 255 /** 256 Trigger one software interrupt to debug agent to handle it. 257 258 @param[in] Signature Software interrupt signature. 259 260 **/ 261 VOID 262 TriggerSoftInterrupt ( 263 IN UINT32 Signature 264 ) 265 { 266 UINTN Dr0; 267 UINTN Dr1; 268 269 // 270 // Save Debug Register State 271 // 272 Dr0 = AsmReadDr0 (); 273 Dr1 = AsmReadDr1 (); 274 275 // 276 // DR0 = Signature 277 // 278 AsmWriteDr0 (SOFT_INTERRUPT_SIGNATURE); 279 AsmWriteDr1 (Signature); 280 281 // 282 // Do INT3 to communicate with HOST side 283 // 284 CpuBreakpoint (); 285 286 // 287 // Restore Debug Register State only when Host didn't change it inside exception handler. 288 // Dr registers can only be changed by setting the HW breakpoint. 289 // 290 AsmWriteDr0 (Dr0); 291 AsmWriteDr1 (Dr1); 292 293 } 294 295 /** 296 Calculate Mailbox checksum and update the checksum field. 297 298 @param[in] Mailbox Debug Agent Mailbox pointer. 299 300 **/ 301 VOID 302 UpdateMailboxChecksum ( 303 IN DEBUG_AGENT_MAILBOX *Mailbox 304 ) 305 { 306 Mailbox->CheckSum = CalculateCheckSum8 ((UINT8 *)Mailbox, sizeof (DEBUG_AGENT_MAILBOX) - 2); 307 } 308 309 /** 310 Verify Mailbox checksum. 311 312 If checksum error, print debug message and run init dead loop. 313 314 @param[in] Mailbox Debug Agent Mailbox pointer. 315 316 **/ 317 VOID 318 VerifyMailboxChecksum ( 319 IN DEBUG_AGENT_MAILBOX *Mailbox 320 ) 321 { 322 UINT8 CheckSum; 323 324 CheckSum = CalculateCheckSum8 ((UINT8 *) Mailbox, sizeof (DEBUG_AGENT_MAILBOX) - 2); 325 // 326 // The checksum updating process may be disturbed by hardware SMI, we need to check CheckSum field 327 // and ToBeCheckSum field to validate the mail box. 328 // 329 if (CheckSum != Mailbox->CheckSum && CheckSum != Mailbox->ToBeCheckSum) { 330 DEBUG ((EFI_D_ERROR, "DebugAgent: Mailbox checksum error, stack or heap crashed!\n")); 331 DEBUG ((EFI_D_ERROR, "DebugAgent: CheckSum = %x, Mailbox->CheckSum = %x, Mailbox->ToBeCheckSum = %x\n", CheckSum, Mailbox->CheckSum, Mailbox->ToBeCheckSum)); 332 CpuDeadLoop (); 333 } 334 } 335 336 /** 337 Update Mailbox content by index. 338 339 @param[in] Mailbox Debug Agent Mailbox pointer. 340 @param[in] Index Mailbox content index. 341 @param[in] Value Value to be set into Mailbox. 342 343 **/ 344 VOID 345 UpdateMailboxContent ( 346 IN DEBUG_AGENT_MAILBOX *Mailbox, 347 IN UINTN Index, 348 IN UINT64 Value 349 ) 350 { 351 AcquireMpSpinLock (&mDebugMpContext.MailboxSpinLock); 352 switch (Index) { 353 case DEBUG_MAILBOX_DEBUG_FLAG_INDEX: 354 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->DebugFlag.Uint64, sizeof(UINT64)) 355 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT64)); 356 Mailbox->DebugFlag.Uint64 = Value; 357 break; 358 case DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX: 359 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->DebugPortHandle, sizeof(UINTN)) 360 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINTN)); 361 Mailbox->DebugPortHandle = (UINTN) Value; 362 break; 363 case DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX: 364 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->ExceptionBufferPointer, sizeof(UINTN)) 365 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINTN)); 366 Mailbox->ExceptionBufferPointer = (UINTN) Value; 367 break; 368 case DEBUG_MAILBOX_LAST_ACK: 369 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->LastAck, sizeof(UINT8)) 370 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8)); 371 Mailbox->LastAck = (UINT8) Value; 372 break; 373 case DEBUG_MAILBOX_SEQUENCE_NO_INDEX: 374 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->SequenceNo, sizeof(UINT8)) 375 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8)); 376 Mailbox->SequenceNo = (UINT8) Value; 377 break; 378 case DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX: 379 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->HostSequenceNo, sizeof(UINT8)) 380 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8)); 381 Mailbox->HostSequenceNo = (UINT8) Value; 382 break; 383 case DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY: 384 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->DebugTimerFrequency, sizeof(UINT32)) 385 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT32)); 386 Mailbox->DebugTimerFrequency = (UINT32) Value; 387 break; 388 } 389 UpdateMailboxChecksum (Mailbox); 390 ReleaseMpSpinLock (&mDebugMpContext.MailboxSpinLock); 391 } 392 393 /** 394 Read data from debug device and save the data in buffer. 395 396 Reads NumberOfBytes data bytes from a debug device into the buffer 397 specified by Buffer. The number of bytes actually read is returned. 398 If the return value is less than NumberOfBytes, then the rest operation failed. 399 If NumberOfBytes is zero, then return 0. 400 401 @param Handle Debug port handle. 402 @param Buffer Pointer to the data buffer to store the data read from the debug device. 403 @param NumberOfBytes Number of bytes which will be read. 404 @param Timeout Timeout value for reading from debug device. It unit is Microsecond. 405 406 @retval 0 Read data failed, no data is to be read. 407 @retval >0 Actual number of bytes read from debug device. 408 409 **/ 410 UINTN 411 DebugAgentReadBuffer ( 412 IN DEBUG_PORT_HANDLE Handle, 413 IN UINT8 *Buffer, 414 IN UINTN NumberOfBytes, 415 IN UINTN Timeout 416 ) 417 { 418 UINTN Index; 419 UINT32 Begin; 420 UINT32 TimeoutTicker; 421 UINT32 TimerRound; 422 UINT32 TimerFrequency; 423 UINT32 TimerCycle; 424 425 Begin = 0; 426 TimeoutTicker = 0; 427 TimerRound = 0; 428 TimerFrequency = GetMailboxPointer()->DebugTimerFrequency; 429 TimerCycle = GetApicTimerInitCount (); 430 431 if (Timeout != 0) { 432 Begin = GetApicTimerCurrentCount (); 433 TimeoutTicker = (UINT32) DivU64x32 ( 434 MultU64x64 ( 435 TimerFrequency, 436 Timeout 437 ), 438 1000000u 439 ); 440 TimerRound = (UINT32) DivU64x32Remainder (TimeoutTicker, TimerCycle / 2, &TimeoutTicker); 441 } 442 Index = 0; 443 while (Index < NumberOfBytes) { 444 if (DebugPortPollBuffer (Handle)) { 445 DebugPortReadBuffer (Handle, Buffer + Index, 1, 0); 446 Index ++; 447 continue; 448 } 449 if (Timeout != 0) { 450 if (TimerRound == 0) { 451 if (IsDebugTimerTimeout (TimerCycle, Begin, TimeoutTicker)) { 452 // 453 // If time out occurs. 454 // 455 return 0; 456 } 457 } else { 458 if (IsDebugTimerTimeout (TimerCycle, Begin, TimerCycle / 2)) { 459 TimerRound --; 460 Begin = GetApicTimerCurrentCount (); 461 } 462 } 463 } 464 } 465 466 return Index; 467 } 468 469 /** 470 Set debug flag in mailbox. 471 472 @param[in] FlagMask Debug flag mask value. 473 @param[in] FlagValue Debug flag value. 474 475 **/ 476 VOID 477 SetDebugFlag ( 478 IN UINT64 FlagMask, 479 IN UINT32 FlagValue 480 ) 481 { 482 DEBUG_AGENT_MAILBOX *Mailbox; 483 UINT64 Data64; 484 485 Mailbox = GetMailboxPointer (); 486 Data64 = (Mailbox->DebugFlag.Uint64 & ~FlagMask) | 487 (LShiftU64 ((UINT64)FlagValue, LowBitSet64 (FlagMask)) & FlagMask); 488 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_FLAG_INDEX, Data64); 489 } 490 491 /** 492 Get debug flag in mailbox. 493 494 @param[in] FlagMask Debug flag mask value. 495 496 @return Debug flag value. 497 498 **/ 499 UINT32 500 GetDebugFlag ( 501 IN UINT64 FlagMask 502 ) 503 { 504 DEBUG_AGENT_MAILBOX *Mailbox; 505 UINT32 DebugFlag; 506 507 Mailbox = GetMailboxPointer (); 508 DebugFlag = (UINT32) RShiftU64 (Mailbox->DebugFlag.Uint64 & FlagMask, LowBitSet64 (FlagMask)); 509 510 return DebugFlag; 511 } 512 513 /** 514 Send a debug message packet to the debug port. 515 516 @param[in] Buffer The debug message. 517 @param[in] Length The length of debug message. 518 519 **/ 520 VOID 521 SendDebugMsgPacket ( 522 IN CHAR8 *Buffer, 523 IN UINTN Length 524 ) 525 { 526 DEBUG_PACKET_HEADER DebugHeader; 527 DEBUG_PORT_HANDLE Handle; 528 529 Handle = GetDebugPortHandle(); 530 531 DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL; 532 DebugHeader.Command = DEBUG_COMMAND_PRINT_MESSAGE; 533 DebugHeader.Length = sizeof (DEBUG_PACKET_HEADER) + (UINT8) Length; 534 DebugHeader.SequenceNo = 0xEE; 535 DebugHeader.Crc = 0; 536 DebugHeader.Crc = CalculateCrc16 ( 537 (UINT8 *)Buffer, Length, 538 CalculateCrc16 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0) 539 ); 540 541 DebugPortWriteBuffer (Handle, (UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER)); 542 DebugPortWriteBuffer (Handle, (UINT8 *)Buffer, Length); 543 } 544 545 /** 546 Prints a debug message to the debug port if the specified error level is enabled. 547 548 If any bit in ErrorLevel is also set in Mainbox, then print the message specified 549 by Format and the associated variable argument list to the debug port. 550 551 @param[in] ErrorLevel The error level of the debug message. 552 @param[in] Format Format string for the debug message to print. 553 @param[in] ... Variable argument list whose contents are accessed 554 based on the format string specified by Format. 555 556 **/ 557 VOID 558 EFIAPI 559 DebugAgentMsgPrint ( 560 IN UINT8 ErrorLevel, 561 IN CHAR8 *Format, 562 ... 563 ) 564 { 565 CHAR8 Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA]; 566 VA_LIST Marker; 567 568 // 569 // Check driver debug mask value and global mask 570 // 571 if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) { 572 return; 573 } 574 575 // 576 // Convert the DEBUG() message to an ASCII String 577 // 578 VA_START (Marker, Format); 579 AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker); 580 VA_END (Marker); 581 582 SendDebugMsgPacket (Buffer, AsciiStrLen (Buffer)); 583 } 584 585 /** 586 Prints a debug message to the debug output device if the specified error level is enabled. 587 588 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function 589 GetDebugPrintErrorLevel (), then print the message specified by Format and the 590 associated variable argument list to the debug output device. 591 592 If Format is NULL, then ASSERT(). 593 594 @param[in] ErrorLevel The error level of the debug message. 595 @param[in] IsSend Flag of debug message to declare that the data is being sent or being received. 596 @param[in] Data Variable argument list whose contents are accessed 597 @param[in] Length based on the format string specified by Format. 598 599 **/ 600 VOID 601 EFIAPI 602 DebugAgentDataMsgPrint ( 603 IN UINT8 ErrorLevel, 604 IN BOOLEAN IsSend, 605 IN UINT8 *Data, 606 IN UINT8 Length 607 ) 608 { 609 CHAR8 Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA]; 610 CHAR8 *DestBuffer; 611 UINTN Index; 612 613 // 614 // Check driver debug mask value and global mask 615 // 616 if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) { 617 return; 618 } 619 620 DestBuffer = Buffer; 621 if (IsSend) { 622 DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA, "Sent data [ "); 623 } else { 624 DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA, "Received data [ "); 625 } 626 627 Index = 0; 628 while (TRUE) { 629 if (DestBuffer - Buffer > DEBUG_DATA_MAXIMUM_REAL_DATA - 6) { 630 // 631 // If there was no enough space in buffer, send out the debug message, 632 // reserving 6 bytes is for the last data and end characters "]\n". 633 // 634 SendDebugMsgPacket (Buffer, DestBuffer - Buffer); 635 DestBuffer = Buffer; 636 } 637 DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "%02x ", Data[Index]); 638 Index ++; 639 if (Index >= Length) { 640 // 641 // The last character of debug message has been foramtted in buffer 642 // 643 DestBuffer += AsciiSPrint(DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "]\n"); 644 SendDebugMsgPacket (Buffer, DestBuffer - Buffer); 645 break; 646 } 647 } 648 } 649 650 /** 651 Read remaing debug packet except for the start symbol 652 653 @param[in] Handle Pointer to Debug Port handle. 654 @param[in, out] DebugHeader Debug header buffer including start symbol. 655 656 @retval EFI_SUCCESS Read the symbol in BreakSymbol. 657 @retval EFI_CRC_ERROR CRC check fail. 658 @retval EFI_TIMEOUT Timeout occurs when reading debug packet. 659 @retval EFI_DEVICE_ERROR Receive the old or responsed packet. 660 661 **/ 662 EFI_STATUS 663 ReadRemainingBreakPacket ( 664 IN DEBUG_PORT_HANDLE Handle, 665 IN OUT DEBUG_PACKET_HEADER *DebugHeader 666 ) 667 { 668 UINT16 Crc; 669 DEBUG_AGENT_MAILBOX *Mailbox; 670 671 // 672 // Has received start symbol, try to read the rest part 673 // 674 if (DebugAgentReadBuffer (Handle, (UINT8 *)DebugHeader + OFFSET_OF (DEBUG_PACKET_HEADER, Command), sizeof (DEBUG_PACKET_HEADER) - OFFSET_OF (DEBUG_PACKET_HEADER, Command), READ_PACKET_TIMEOUT) == 0) { 675 // 676 // Timeout occur, exit 677 // 678 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Timeout in Debug Timer interrupt\n"); 679 return EFI_TIMEOUT; 680 } 681 682 Crc = DebugHeader->Crc; 683 DebugHeader->Crc = 0; 684 if (CalculateCrc16 ((UINT8 *)DebugHeader, DebugHeader->Length, 0) != Crc) { 685 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Debug Timer CRC (%x) against (%x)\n", Crc, CalculateCrc16 ((UINT8 *) &DebugHeader, DebugHeader->Length, 0)); 686 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *)DebugHeader, DebugHeader->Length); 687 return EFI_CRC_ERROR; 688 } 689 Mailbox = GetMailboxPointer(); 690 if (IS_REQUEST (DebugHeader)) { 691 if (DebugHeader->SequenceNo == (UINT8) (Mailbox->HostSequenceNo + 1)) { 692 // 693 // Only updagte HostSequenceNo for new command packet 694 // 695 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, DebugHeader->SequenceNo); 696 return EFI_SUCCESS; 697 } 698 if (DebugHeader->SequenceNo == Mailbox->HostSequenceNo) { 699 return EFI_SUCCESS; 700 } 701 } 702 703 return EFI_DEVICE_ERROR; 704 } 705 706 /** 707 Check if HOST is attached based on Mailbox. 708 709 @retval TRUE HOST is attached. 710 @retval FALSE HOST is not attached. 711 712 **/ 713 BOOLEAN 714 IsHostAttached ( 715 VOID 716 ) 717 { 718 return (BOOLEAN) (GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED) == 1); 719 } 720 721 /** 722 Set HOST connect flag in Mailbox. 723 724 @param[in] Attached Attach status. 725 726 **/ 727 VOID 728 SetHostAttached ( 729 IN BOOLEAN Attached 730 ) 731 { 732 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Attach status is %d\n", Attached); 733 SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED, (UINT32)Attached); 734 } 735 736 /** 737 Set debug setting of Debug Agent in Mailbox. 738 739 @param DebugSetting Pointer to Debug Setting defined by transfer protocol. 740 741 @retval RETURN_SUCCESS The setting is set successfully. 742 @retval RETURN_UNSUPPORTED The Key value is not supported. 743 744 **/ 745 RETURN_STATUS 746 SetDebugSetting ( 747 IN DEBUG_DATA_SET_DEBUG_SETTING *DebugSetting 748 ) 749 { 750 RETURN_STATUS Status; 751 752 Status = RETURN_SUCCESS; 753 switch (DebugSetting->Key) { 754 case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK: 755 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI, DebugSetting->Value); 756 break; 757 case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL: 758 SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL, DebugSetting->Value); 759 break; 760 case DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK: 761 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT, DebugSetting->Value); 762 break; 763 default: 764 Status = RETURN_UNSUPPORTED; 765 } 766 return Status; 767 } 768 769 /** 770 Exectue GO command. 771 772 @param[in] CpuContext Pointer to saved CPU context. 773 774 **/ 775 VOID 776 CommandGo ( 777 IN DEBUG_CPU_CONTEXT *CpuContext 778 ) 779 { 780 IA32_EFLAGS32 *Eflags; 781 782 Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags; 783 Eflags->Bits.TF = 0; 784 Eflags->Bits.RF = 1; 785 } 786 787 /** 788 Execute Stepping command. 789 790 @param[in] CpuContext Pointer to saved CPU context. 791 792 **/ 793 VOID 794 CommandStepping ( 795 IN DEBUG_CPU_CONTEXT *CpuContext 796 ) 797 { 798 IA32_EFLAGS32 *Eflags; 799 800 Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags; 801 Eflags->Bits.TF = 1; 802 Eflags->Bits.RF = 1; 803 // 804 // Save and clear EFLAGS.IF to avoid interrupt happen when executing Stepping 805 // 806 SetDebugFlag (DEBUG_AGENT_FLAG_INTERRUPT_FLAG, Eflags->Bits.IF); 807 Eflags->Bits.IF = 0; 808 // 809 // Set Stepping Flag 810 // 811 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 1); 812 } 813 814 /** 815 Do some cleanup after Stepping command done. 816 817 @param[in] CpuContext Pointer to saved CPU context. 818 819 **/ 820 VOID 821 CommandSteppingCleanup ( 822 IN DEBUG_CPU_CONTEXT *CpuContext 823 ) 824 { 825 IA32_EFLAGS32 *Eflags; 826 827 Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags; 828 // 829 // Restore EFLAGS.IF 830 // 831 Eflags->Bits.IF = GetDebugFlag (DEBUG_AGENT_FLAG_INTERRUPT_FLAG); 832 // 833 // Clear Stepping flag 834 // 835 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 0); 836 } 837 838 /** 839 Set debug register for hardware breakpoint. 840 841 @param[in] CpuContext Pointer to saved CPU context. 842 @param[in] SetHwBreakpoint Hardware breakpoint to be set. 843 844 **/ 845 VOID 846 SetDebugRegister ( 847 IN DEBUG_CPU_CONTEXT *CpuContext, 848 IN DEBUG_DATA_SET_HW_BREAKPOINT *SetHwBreakpoint 849 ) 850 { 851 UINT8 RegisterIndex; 852 UINTN Dr7Value; 853 854 RegisterIndex = SetHwBreakpoint->Type.Index; 855 856 // 857 // Set debug address 858 // 859 * ((UINTN *) &CpuContext->Dr0 + RegisterIndex) = (UINTN) SetHwBreakpoint->Address; 860 861 Dr7Value = CpuContext->Dr7; 862 863 // 864 // Enable Gx, Lx 865 // 866 Dr7Value |= (UINTN) (0x3 << (RegisterIndex * 2)); 867 // 868 // Set RWx and Lenx 869 // 870 Dr7Value &= (UINTN) (~(0xf << (16 + RegisterIndex * 4))); 871 Dr7Value |= (UINTN) ((SetHwBreakpoint->Type.Length << 2) | SetHwBreakpoint->Type.Access) << (16 + RegisterIndex * 4); 872 // 873 // Enable GE, LE 874 // 875 Dr7Value |= 0x300; 876 877 CpuContext->Dr7 = Dr7Value; 878 } 879 880 /** 881 Clear debug register for hardware breakpoint. 882 883 @param[in] CpuContext Pointer to saved CPU context. 884 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared. 885 886 **/ 887 VOID 888 ClearDebugRegister ( 889 IN DEBUG_CPU_CONTEXT *CpuContext, 890 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT *ClearHwBreakpoint 891 ) 892 { 893 if ((ClearHwBreakpoint->IndexMask & BIT0) != 0) { 894 CpuContext->Dr0 = 0; 895 CpuContext->Dr7 &= (UINTN)(~(0x3 << 0)); 896 } 897 if ((ClearHwBreakpoint->IndexMask & BIT1) != 0) { 898 CpuContext->Dr1 = 0; 899 CpuContext->Dr7 &= (UINTN)(~(0x3 << 2)); 900 } 901 if ((ClearHwBreakpoint->IndexMask & BIT2) != 0) { 902 CpuContext->Dr2 = 0; 903 CpuContext->Dr7 &= (UINTN)(~(0x3 << 4)); 904 } 905 if ((ClearHwBreakpoint->IndexMask & BIT3) != 0) { 906 CpuContext->Dr3 = 0; 907 CpuContext->Dr7 &= (UINTN)(~(0x3 << 6)); 908 } 909 } 910 911 912 /** 913 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index. 914 915 @param[in] Index Register index. 916 @param[out] Width Register width returned. 917 918 @return Offset in the FPU Save State. 919 920 **/ 921 UINT16 922 ArchReadFxStatOffset ( 923 IN UINT8 Index, 924 OUT UINT8 *Width 925 ) 926 { 927 if (Index < SOFT_DEBUGGER_REGISTER_ST0) { 928 switch (Index) { 929 case SOFT_DEBUGGER_REGISTER_FP_FCW: 930 *Width = (UINT8) sizeof (UINT16); 931 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Fcw); 932 933 case SOFT_DEBUGGER_REGISTER_FP_FSW: 934 *Width = (UINT8) sizeof (UINT16); 935 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Fsw); 936 937 case SOFT_DEBUGGER_REGISTER_FP_FTW: 938 *Width = (UINT8) sizeof (UINT16); 939 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Ftw); 940 941 case SOFT_DEBUGGER_REGISTER_FP_OPCODE: 942 *Width = (UINT8) sizeof (UINT16); 943 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Opcode); 944 945 case SOFT_DEBUGGER_REGISTER_FP_EIP: 946 *Width = (UINT8) sizeof (UINT32); 947 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Eip); 948 949 case SOFT_DEBUGGER_REGISTER_FP_CS: 950 *Width = (UINT8) sizeof (UINT16); 951 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Cs); 952 953 case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET: 954 *Width = (UINT8) sizeof (UINT32); 955 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, DataOffset); 956 957 case SOFT_DEBUGGER_REGISTER_FP_DS: 958 *Width = (UINT8) sizeof (UINT16); 959 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Ds); 960 961 case SOFT_DEBUGGER_REGISTER_FP_MXCSR: 962 *Width = (UINT8) sizeof (UINT32); 963 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Mxcsr); 964 965 case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK: 966 *Width = (UINT8) sizeof (UINT32); 967 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Mxcsr_Mask); 968 } 969 } 970 971 if (Index <= SOFT_DEBUGGER_REGISTER_ST7) { 972 *Width = 10; 973 } else if (Index <= SOFT_DEBUGGER_REGISTER_XMM15) { 974 *Width = 16; 975 } else { 976 // 977 // MMX register 978 // 979 *Width = 8; 980 Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0; 981 } 982 983 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, St0Mm0) + (Index - SOFT_DEBUGGER_REGISTER_ST0) * 16; 984 } 985 986 /** 987 Return the pointer of the register value in the CPU saved context. 988 989 @param[in] CpuContext Pointer to saved CPU context. 990 @param[in] Index Register index value. 991 @param[out] Width Data width to read. 992 993 @return The pointer in the CPU saved context. 994 995 **/ 996 UINT8 * 997 ArchReadRegisterBuffer ( 998 IN DEBUG_CPU_CONTEXT *CpuContext, 999 IN UINT8 Index, 1000 OUT UINT8 *Width 1001 ) 1002 { 1003 UINT8 *Buffer; 1004 1005 if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) { 1006 Buffer = (UINT8 *) CpuContext + OFFSET_OF (DEBUG_CPU_CONTEXT, Dr0) + Index * sizeof (UINTN); 1007 *Width = (UINT8) sizeof (UINTN); 1008 } else { 1009 // 1010 // FPU/MMX/XMM registers 1011 // 1012 Buffer = (UINT8 *) CpuContext + OFFSET_OF (DEBUG_CPU_CONTEXT, FxSaveState) + ArchReadFxStatOffset (Index, Width); 1013 } 1014 1015 return Buffer; 1016 } 1017 1018 /** 1019 Send the packet without data to HOST. 1020 1021 @param[in] CommandType Type of Command. 1022 @param[in] SequenceNo Sequence number. 1023 1024 **/ 1025 VOID 1026 SendPacketWithoutData ( 1027 IN UINT8 CommandType, 1028 IN UINT8 SequenceNo 1029 ) 1030 { 1031 DEBUG_PACKET_HEADER DebugHeader; 1032 DEBUG_PORT_HANDLE Handle; 1033 1034 Handle = GetDebugPortHandle(); 1035 1036 DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL; 1037 DebugHeader.Command = CommandType; 1038 DebugHeader.Length = sizeof (DEBUG_PACKET_HEADER); 1039 DebugHeader.SequenceNo = SequenceNo; 1040 DebugHeader.Crc = 0; 1041 DebugHeader.Crc = CalculateCrc16 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0); 1042 1043 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) &DebugHeader, DebugHeader.Length); 1044 DebugPortWriteBuffer (Handle, (UINT8 *) &DebugHeader, DebugHeader.Length); 1045 } 1046 1047 /** 1048 Send acknowledge packet to HOST. 1049 1050 @param[in] AckCommand Type of Acknowledge packet. 1051 1052 **/ 1053 VOID 1054 SendAckPacket ( 1055 IN UINT8 AckCommand 1056 ) 1057 { 1058 UINT8 SequenceNo; 1059 DEBUG_AGENT_MAILBOX *Mailbox; 1060 1061 if (AckCommand != DEBUG_COMMAND_OK) { 1062 // 1063 // This is not ACK OK packet 1064 // 1065 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Send ACK(%d)\n", AckCommand); 1066 } 1067 Mailbox = GetMailboxPointer(); 1068 SequenceNo = Mailbox->HostSequenceNo; 1069 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "SendAckPacket: SequenceNo = %x\n", SequenceNo); 1070 SendPacketWithoutData (AckCommand, SequenceNo); 1071 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_LAST_ACK, AckCommand); 1072 } 1073 1074 /** 1075 Decompress the Data in place. 1076 1077 @param[in, out] Data The compressed data buffer. 1078 The buffer is assumed large enough to hold the uncompressed data. 1079 @param[in] Length The length of the compressed data buffer. 1080 1081 @return The length of the uncompressed data buffer. 1082 **/ 1083 UINT8 1084 DecompressDataInPlace ( 1085 IN OUT UINT8 *Data, 1086 IN UINTN Length 1087 ) 1088 { 1089 UINTN Index; 1090 UINT16 LastChar; 1091 UINTN LastCharCount; 1092 UINT8 CurrentChar; 1093 1094 LastChar = (UINT16) -1; 1095 LastCharCount = 0; 1096 for (Index = 0; Index < Length; Index++) { 1097 CurrentChar = Data[Index]; 1098 if (LastCharCount == 2) { 1099 LastCharCount = 0; 1100 CopyMem (&Data[Index + CurrentChar], &Data[Index + 1], Length - Index - 1); 1101 SetMem (&Data[Index], CurrentChar, (UINT8) LastChar); 1102 LastChar = (UINT16) -1; 1103 Index += CurrentChar - 1; 1104 Length += CurrentChar - 1; 1105 } else { 1106 if (LastChar != CurrentChar) { 1107 LastCharCount = 0; 1108 } 1109 LastCharCount++; 1110 LastChar = CurrentChar; 1111 } 1112 } 1113 1114 ASSERT (Length <= DEBUG_DATA_MAXIMUM_REAL_DATA); 1115 1116 return (UINT8) Length; 1117 } 1118 1119 /** 1120 Receive valid packet from HOST. 1121 1122 @param[out] InputPacket Buffer to receive packet. 1123 @param[out] BreakReceived TRUE means break-in symbol received. 1124 FALSE means break-in symbol not received. 1125 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return 1126 TRUE: Compatible packet received. 1127 FALSE: Incompatible packet received. 1128 @param[in] Timeout Time out value to wait for acknowlege from HOST. 1129 The unit is microsecond. 1130 @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol. 1131 FALSE: Does not Skip time out when reading start symbol. 1132 1133 @retval RETURN_SUCCESS A valid package was reveived in InputPacket. 1134 @retval RETURN_TIMEOUT Timeout occurs. 1135 1136 **/ 1137 RETURN_STATUS 1138 ReceivePacket ( 1139 OUT UINT8 *InputPacket, 1140 OUT BOOLEAN *BreakReceived, 1141 OUT BOOLEAN *IncompatibilityFlag, OPTIONAL 1142 IN UINTN Timeout, 1143 IN BOOLEAN SkipStartSymbol 1144 ) 1145 { 1146 DEBUG_PACKET_HEADER *DebugHeader; 1147 UINTN Received; 1148 DEBUG_PORT_HANDLE Handle; 1149 UINT16 Crc; 1150 UINTN TimeoutForStartSymbol; 1151 1152 Handle = GetDebugPortHandle(); 1153 if (SkipStartSymbol) { 1154 TimeoutForStartSymbol = 0; 1155 } else { 1156 TimeoutForStartSymbol = Timeout; 1157 } 1158 1159 DebugHeader = (DEBUG_PACKET_HEADER *) InputPacket; 1160 while (TRUE) { 1161 // 1162 // Find the valid start symbol 1163 // 1164 Received = DebugAgentReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), TimeoutForStartSymbol); 1165 if (Received < sizeof (DebugHeader->StartSymbol)) { 1166 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "DebugAgentReadBuffer(StartSymbol) timeout\n"); 1167 return RETURN_TIMEOUT; 1168 } 1169 1170 if ((DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_NORMAL) && (DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_COMPRESS)) { 1171 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Invalid start symbol received [%02x]\n", DebugHeader->StartSymbol); 1172 continue; 1173 } 1174 1175 // 1176 // Read Package header till field Length 1177 // 1178 Received = DebugAgentReadBuffer ( 1179 Handle, 1180 (UINT8 *) DebugHeader + OFFSET_OF (DEBUG_PACKET_HEADER, Command), 1181 OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader->Length) - sizeof (DebugHeader->StartSymbol), 1182 Timeout 1183 ); 1184 if (Received == 0) { 1185 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugAgentReadBuffer(Command) timeout\n"); 1186 return RETURN_TIMEOUT; 1187 } 1188 if (DebugHeader->Length < sizeof (DEBUG_PACKET_HEADER)) { 1189 if (IncompatibilityFlag != NULL) { 1190 // 1191 // This is one old version debug packet format, set Incompatibility flag 1192 // 1193 *IncompatibilityFlag = TRUE; 1194 } else { 1195 // 1196 // Skip the bad small packet 1197 // 1198 continue; 1199 } 1200 } else { 1201 // 1202 // Read the payload data include the CRC field 1203 // 1204 Received = DebugAgentReadBuffer (Handle, &DebugHeader->SequenceNo, (UINT8) (DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, SequenceNo)), Timeout); 1205 if (Received == 0) { 1206 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugAgentReadBuffer(SequenceNo) timeout\n"); 1207 return RETURN_TIMEOUT; 1208 } 1209 // 1210 // Calculate the CRC of Debug Packet 1211 // 1212 Crc = DebugHeader->Crc; 1213 DebugHeader->Crc = 0; 1214 if (Crc == CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0)) { 1215 break; 1216 } 1217 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "CRC Error (received CRC is %x)\n", Crc); 1218 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length); 1219 } 1220 } 1221 1222 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length); 1223 1224 if (DebugHeader->StartSymbol == DEBUG_STARTING_SYMBOL_COMPRESS) { 1225 DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL; 1226 DebugHeader->Length = DecompressDataInPlace ( 1227 (UINT8 *) (DebugHeader + 1), DebugHeader->Length - sizeof (DEBUG_PACKET_HEADER) 1228 ) + sizeof (DEBUG_PACKET_HEADER); 1229 } 1230 return RETURN_SUCCESS; 1231 } 1232 1233 /** 1234 Receive acknowledge packet OK from HOST in specified time. 1235 1236 @param[in] Command The command type issued by TARGET. 1237 @param[in] Timeout Time out value to wait for acknowlege from HOST. 1238 The unit is microsecond. 1239 @param[out] BreakReceived If BreakReceived is not NULL, 1240 TRUE is retured if break-in symbol received. 1241 FALSE is retured if break-in symbol not received. 1242 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return 1243 TRUE: Compatible packet received. 1244 FALSE: Incompatible packet received. 1245 1246 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST, 1247 the type of acknowlege packet saved in Ack. 1248 @retval RETURN_TIMEOUT Specified timeout value was up. 1249 1250 **/ 1251 RETURN_STATUS 1252 SendCommandAndWaitForAckOK ( 1253 IN UINT8 Command, 1254 IN UINTN Timeout, 1255 OUT BOOLEAN *BreakReceived, OPTIONAL 1256 OUT BOOLEAN *IncompatibilityFlag OPTIONAL 1257 ) 1258 { 1259 RETURN_STATUS Status; 1260 UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT]; 1261 DEBUG_PACKET_HEADER *DebugHeader; 1262 UINT8 SequenceNo; 1263 UINT8 HostSequenceNo; 1264 UINT8 RetryCount; 1265 1266 RetryCount = 3; 1267 DebugHeader = (DEBUG_PACKET_HEADER *) InputPacketBuffer; 1268 Status = RETURN_TIMEOUT; 1269 while (RetryCount > 0) { 1270 SequenceNo = GetMailboxPointer()->SequenceNo; 1271 HostSequenceNo = GetMailboxPointer()->HostSequenceNo; 1272 SendPacketWithoutData (Command, SequenceNo); 1273 Status = ReceivePacket ((UINT8 *) DebugHeader, BreakReceived, IncompatibilityFlag, Timeout, FALSE); 1274 if (Status == RETURN_TIMEOUT) { 1275 if (Command == DEBUG_COMMAND_INIT_BREAK) { 1276 RetryCount--; 1277 } else { 1278 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout when waiting for ACK packet.\n"); 1279 } 1280 continue; 1281 } 1282 ASSERT_EFI_ERROR (Status); 1283 // 1284 // Status == RETURN_SUCCESS 1285 // 1286 if (DebugHeader->Command == DEBUG_COMMAND_OK && DebugHeader->SequenceNo == SequenceNo) { 1287 // 1288 // Received Ack OK 1289 // 1290 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_SEQUENCE_NO_INDEX, ++SequenceNo); 1291 return Status; 1292 } 1293 if (DebugHeader->Command == DEBUG_COMMAND_GO && (DebugHeader->SequenceNo == HostSequenceNo || Command == DEBUG_COMMAND_INIT_BREAK)) { 1294 // 1295 // Received Old GO 1296 // 1297 if (Command == DEBUG_COMMAND_INIT_BREAK) { 1298 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive GO() in last boot\n"); 1299 } 1300 SendPacketWithoutData (DEBUG_COMMAND_OK, DebugHeader->SequenceNo); 1301 } 1302 } 1303 1304 ASSERT (Command == DEBUG_COMMAND_INIT_BREAK); 1305 return Status; 1306 } 1307 1308 /** 1309 Get current break cause. 1310 1311 @param[in] Vector Vector value of exception or interrupt. 1312 @param[in] CpuContext Pointer to save CPU context. 1313 1314 @return The type of break cause defined by XXXX 1315 1316 **/ 1317 UINT8 1318 GetBreakCause ( 1319 IN UINTN Vector, 1320 IN DEBUG_CPU_CONTEXT *CpuContext 1321 ) 1322 { 1323 UINT8 Cause; 1324 1325 Cause = DEBUG_DATA_BREAK_CAUSE_UNKNOWN; 1326 1327 switch (Vector) { 1328 case DEBUG_INT1_VECTOR: 1329 case DEBUG_INT3_VECTOR: 1330 1331 if (Vector == DEBUG_INT1_VECTOR) { 1332 // 1333 // INT 1 1334 // 1335 if ((CpuContext->Dr6 & BIT14) != 0) { 1336 Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING; 1337 // 1338 // DR6.BIT14 Indicates (when set) that the debug exception was 1339 // triggered by the single step execution mode. 1340 // The single-step mode is the highest priority debug exception. 1341 // This is single step, no need to check DR0, to ensure single step 1342 // work in PeCoffExtraActionLib (right after triggering a breakpoint 1343 // to report image load/unload). 1344 // 1345 return Cause; 1346 1347 } else { 1348 Cause = DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT; 1349 } 1350 } else { 1351 // 1352 // INT 3 1353 // 1354 Cause = DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT; 1355 } 1356 1357 switch (CpuContext->Dr0) { 1358 case IMAGE_LOAD_SIGNATURE: 1359 case IMAGE_UNLOAD_SIGNATURE: 1360 1361 if (CpuContext->Dr3 == IO_PORT_BREAKPOINT_ADDRESS) { 1362 1363 Cause = (UINT8) ((CpuContext->Dr0 == IMAGE_LOAD_SIGNATURE) ? 1364 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD : DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD); 1365 } 1366 break; 1367 1368 case SOFT_INTERRUPT_SIGNATURE: 1369 1370 if (CpuContext->Dr1 == MEMORY_READY_SIGNATURE) { 1371 Cause = DEBUG_DATA_BREAK_CAUSE_MEMORY_READY; 1372 CpuContext->Dr0 = 0; 1373 } else if (CpuContext->Dr1 == SYSTEM_RESET_SIGNATURE) { 1374 Cause = DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET; 1375 CpuContext->Dr0 = 0; 1376 } 1377 break; 1378 1379 default: 1380 break; 1381 1382 } 1383 1384 break; 1385 1386 case DEBUG_TIMER_VECTOR: 1387 Cause = DEBUG_DATA_BREAK_CAUSE_USER_HALT; 1388 break; 1389 1390 default: 1391 if (Vector < 20) { 1392 if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) == 1) { 1393 // 1394 // If stepping command is executing 1395 // 1396 Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING; 1397 } else { 1398 Cause = DEBUG_DATA_BREAK_CAUSE_EXCEPTION; 1399 } 1400 } 1401 break; 1402 } 1403 1404 return Cause; 1405 } 1406 1407 /** 1408 Copy memory from source to destination with specified width. 1409 1410 @param[out] Dest A pointer to the destination buffer of the memory copy. 1411 @param[in] Src A pointer to the source buffer of the memory copy. 1412 @param[in] Count The number of data with specified width to copy from source to destination. 1413 @param[in] Width Data width in byte. 1414 1415 **/ 1416 VOID 1417 CopyMemByWidth ( 1418 OUT UINT8 *Dest, 1419 IN UINT8 *Src, 1420 IN UINT16 Count, 1421 IN UINT8 Width 1422 ) 1423 { 1424 UINT8 *Destination; 1425 UINT8 *Source; 1426 INT8 Step; 1427 1428 if (Src > Dest) { 1429 Destination = Dest; 1430 Source = Src; 1431 Step = Width; 1432 } else { 1433 // 1434 // Copy memory from tail to avoid memory overlap 1435 // 1436 Destination = Dest + (Count - 1) * Width; 1437 Source = Src + (Count - 1) * Width; 1438 Step = -Width; 1439 } 1440 1441 while (Count-- != 0) { 1442 switch (Width) { 1443 case 1: 1444 *(UINT8 *) Destination = MmioRead8 ((UINTN) Source); 1445 break; 1446 case 2: 1447 *(UINT16 *) Destination = MmioRead16 ((UINTN) Source); 1448 break; 1449 case 4: 1450 *(UINT32 *) Destination = MmioRead32 ((UINTN) Source); 1451 break; 1452 case 8: 1453 *(UINT64 *) Destination = MmioRead64 ((UINTN) Source); 1454 break; 1455 default: 1456 ASSERT (FALSE); 1457 } 1458 Source += Step; 1459 Destination += Step; 1460 } 1461 } 1462 1463 /** 1464 Compress the data buffer but do not modify the original buffer. 1465 1466 The compressed data is directly send to the debug channel. 1467 Compressing in place doesn't work because the data may become larger 1468 during compressing phase. ("3 3 ..." --> "3 3 0 ...") 1469 The routine is expected to be called three times: 1470 1. Compute the length of the compressed data buffer; 1471 2. Compute the CRC of the compressed data buffer; 1472 3. Compress the data and send to the debug channel. 1473 1474 @param[in] Handle The debug channel handle to send the compressed data buffer. 1475 @param[in] Data The data buffer. 1476 @param[in] Length The length of the data buffer. 1477 @param[in] Send TRUE to send the compressed data buffer. 1478 @param[out] CompressedLength Return the length of the compressed data buffer. 1479 It may be larger than the Length in some cases. 1480 @param[out] CompressedCrc Return the CRC of the compressed data buffer. 1481 **/ 1482 VOID 1483 CompressData ( 1484 IN DEBUG_PORT_HANDLE Handle, 1485 IN UINT8 *Data, 1486 IN UINT8 Length, 1487 IN BOOLEAN Send, 1488 OUT UINTN *CompressedLength, OPTIONAL 1489 OUT UINT16 *CompressedCrc OPTIONAL 1490 ) 1491 { 1492 UINTN Index; 1493 UINT8 LastChar; 1494 UINT8 LastCharCount; 1495 UINT8 CurrentChar; 1496 UINTN CompressedIndex; 1497 1498 ASSERT (Length > 0); 1499 LastChar = Data[0] + 1; // Just ensure it's different from the first byte. 1500 LastCharCount = 0; 1501 1502 for (Index = 0, CompressedIndex = 0; Index <= Length; Index++) { 1503 if (Index < Length) { 1504 CurrentChar = Data[Index]; 1505 } else { 1506 CurrentChar = (UINT8) LastChar + 1; // just ensure it's different from LastChar 1507 } 1508 if (LastChar != CurrentChar) { 1509 if (LastCharCount == 1) { 1510 CompressedIndex++; 1511 if (CompressedCrc != NULL) { 1512 *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc); 1513 } 1514 if (Send) { 1515 DebugPortWriteBuffer (Handle, &LastChar, 1); 1516 } 1517 1518 } else if (LastCharCount >= 2) { 1519 CompressedIndex += 3; 1520 LastCharCount -= 2; 1521 if (CompressedCrc != NULL) { 1522 *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc); 1523 *CompressedCrc = CalculateCrc16 (&LastChar, 1, *CompressedCrc); 1524 *CompressedCrc = CalculateCrc16 (&LastCharCount, 1, *CompressedCrc); 1525 } 1526 if (Send) { 1527 DebugPortWriteBuffer (Handle, &LastChar, 1); 1528 DebugPortWriteBuffer (Handle, &LastChar, 1); 1529 DebugPortWriteBuffer (Handle, &LastCharCount, 1); 1530 } 1531 } 1532 LastCharCount = 0; 1533 } 1534 LastCharCount++; 1535 LastChar = CurrentChar; 1536 } 1537 1538 if (CompressedLength != NULL) { 1539 *CompressedLength = CompressedIndex; 1540 } 1541 } 1542 1543 /** 1544 Read memory with speicifed width and send packet with response data to HOST. 1545 1546 @param[in] Data Pointer to response data buffer. 1547 @param[in] Count The number of data with specified Width. 1548 @param[in] Width Data width in byte. 1549 @param[in] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet, 1550 to minimize the stack usage. 1551 1552 @retval RETURN_SUCCESS Response data was sent successfully. 1553 1554 **/ 1555 RETURN_STATUS 1556 ReadMemoryAndSendResponsePacket ( 1557 IN UINT8 *Data, 1558 IN UINT16 Count, 1559 IN UINT8 Width, 1560 IN DEBUG_PACKET_HEADER *DebugHeader 1561 ) 1562 { 1563 RETURN_STATUS Status; 1564 BOOLEAN LastPacket; 1565 DEBUG_PORT_HANDLE Handle; 1566 UINT8 SequenceNo; 1567 UINTN RemainingDataSize; 1568 UINT8 CurrentDataSize; 1569 UINTN CompressedDataSize; 1570 1571 Handle = GetDebugPortHandle(); 1572 1573 RemainingDataSize = Count * Width; 1574 while (TRUE) { 1575 SequenceNo = GetMailboxPointer()->HostSequenceNo; 1576 if (RemainingDataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) { 1577 // 1578 // If the remaining data is less one real packet size, this is the last data packet 1579 // 1580 CurrentDataSize = (UINT8) RemainingDataSize; 1581 LastPacket = TRUE; 1582 DebugHeader->Command = DEBUG_COMMAND_OK; 1583 } else { 1584 // 1585 // Data is too larger to be sent in one packet, calculate the actual data size could 1586 // be sent in one Maximum data packet 1587 // 1588 CurrentDataSize = (DEBUG_DATA_MAXIMUM_REAL_DATA / Width) * Width; 1589 LastPacket = FALSE; 1590 DebugHeader->Command = DEBUG_COMMAND_IN_PROGRESS; 1591 } 1592 // 1593 // Construct the rest Debug header 1594 // 1595 DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL; 1596 DebugHeader->Length = CurrentDataSize + sizeof (DEBUG_PACKET_HEADER); 1597 DebugHeader->SequenceNo = SequenceNo; 1598 DebugHeader->Crc = 0; 1599 CopyMemByWidth ((UINT8 *) (DebugHeader + 1), Data, CurrentDataSize / Width, Width); 1600 1601 // 1602 // Compression/decompression support was added since revision 0.4. 1603 // Revision 0.3 shouldn't compress the packet. 1604 // 1605 if (DEBUG_AGENT_REVISION >= DEBUG_AGENT_REVISION_04) { 1606 // 1607 // Get the compressed data size without modifying the packet. 1608 // 1609 CompressData ( 1610 Handle, 1611 (UINT8 *) (DebugHeader + 1), 1612 CurrentDataSize, 1613 FALSE, 1614 &CompressedDataSize, 1615 NULL 1616 ); 1617 } else { 1618 CompressedDataSize = CurrentDataSize; 1619 } 1620 if (CompressedDataSize < CurrentDataSize) { 1621 DebugHeader->Length = (UINT8) CompressedDataSize + sizeof (DEBUG_PACKET_HEADER); 1622 DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_COMPRESS; 1623 // 1624 // Compute the CRC of the packet head without modifying the packet. 1625 // 1626 DebugHeader->Crc = CalculateCrc16 ((UINT8 *) DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0); 1627 CompressData ( 1628 Handle, 1629 (UINT8 *) (DebugHeader + 1), 1630 CurrentDataSize, 1631 FALSE, 1632 NULL, 1633 &DebugHeader->Crc 1634 ); 1635 // 1636 // Send out the packet head. 1637 // 1638 DebugPortWriteBuffer (Handle, (UINT8 *) DebugHeader, sizeof (DEBUG_PACKET_HEADER)); 1639 // 1640 // Compress and send out the packet data. 1641 // 1642 CompressData ( 1643 Handle, 1644 (UINT8 *) (DebugHeader + 1), 1645 CurrentDataSize, 1646 TRUE, 1647 NULL, 1648 NULL 1649 ); 1650 } else { 1651 1652 // 1653 // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 () 1654 // 1655 DebugHeader->Crc = CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0); 1656 1657 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) DebugHeader, DebugHeader->Length); 1658 1659 DebugPortWriteBuffer (Handle, (UINT8 *) DebugHeader, DebugHeader->Length); 1660 } 1661 1662 while (TRUE) { 1663 Status = ReceivePacket ((UINT8 *) DebugHeader, NULL, NULL, READ_PACKET_TIMEOUT, FALSE); 1664 if (Status == RETURN_TIMEOUT) { 1665 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout in SendDataResponsePacket()\n"); 1666 break; 1667 } 1668 if ((DebugHeader->Command == DEBUG_COMMAND_OK) && (DebugHeader->SequenceNo == SequenceNo) && LastPacket) { 1669 // 1670 // If this is the last packet, return RETURN_SUCCESS. 1671 // 1672 return RETURN_SUCCESS; 1673 } 1674 if ((DebugHeader->Command == DEBUG_COMMAND_CONTINUE) && (DebugHeader->SequenceNo == (UINT8) (SequenceNo + 1))) { 1675 // 1676 // Calculate the rest data size 1677 // 1678 Data += CurrentDataSize; 1679 RemainingDataSize -= CurrentDataSize; 1680 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, DebugHeader->SequenceNo); 1681 break; 1682 } 1683 if (DebugHeader->SequenceNo >= SequenceNo) { 1684 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo, DebugHeader->SequenceNo); 1685 break; 1686 } 1687 } 1688 } 1689 } 1690 1691 /** 1692 Send packet with response data to HOST. 1693 1694 @param[in] Data Pointer to response data buffer. 1695 @param[in] DataSize Size of response data in byte. 1696 @param[in, out] DebugHeader Pointer to a buffer for creating response packet and receiving ACK packet, 1697 to minimize the stack usage. 1698 1699 @retval RETURN_SUCCESS Response data was sent successfully. 1700 1701 **/ 1702 RETURN_STATUS 1703 SendDataResponsePacket ( 1704 IN UINT8 *Data, 1705 IN UINT16 DataSize, 1706 IN OUT DEBUG_PACKET_HEADER *DebugHeader 1707 ) 1708 { 1709 return ReadMemoryAndSendResponsePacket (Data, DataSize, 1, DebugHeader); 1710 } 1711 1712 /** 1713 Try to attach the HOST. 1714 1715 Send init break packet to HOST: 1716 If no acknowlege received in specified Timeout, return RETURN_TIMEOUT. 1717 If received acknowlege, check the revision of HOST. 1718 Set Attach Flag if attach successfully. 1719 1720 @param[in] BreakCause Break cause of this break event. 1721 @param[in] Timeout Time out value to wait for acknowlege from HOST. 1722 The unit is microsecond. 1723 @param[out] BreakReceived If BreakReceived is not NULL, 1724 TRUE is retured if break-in symbol received. 1725 FALSE is retured if break-in symbol not received. 1726 **/ 1727 RETURN_STATUS 1728 AttachHost ( 1729 IN UINT8 BreakCause, 1730 IN UINTN Timeout, 1731 OUT BOOLEAN *BreakReceived 1732 ) 1733 { 1734 RETURN_STATUS Status; 1735 DEBUG_PORT_HANDLE Handle; 1736 BOOLEAN IncompatibilityFlag; 1737 1738 IncompatibilityFlag = FALSE; 1739 Handle = GetDebugPortHandle(); 1740 1741 // 1742 // Send init break and wait ack in Timeout 1743 // 1744 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgSendInitPacket, AsciiStrLen (mErrorMsgSendInitPacket)); 1745 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET) { 1746 Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK, Timeout, BreakReceived, &IncompatibilityFlag); 1747 } else { 1748 Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK, Timeout, BreakReceived, &IncompatibilityFlag); 1749 } 1750 if (IncompatibilityFlag) { 1751 // 1752 // If the incompatible Debug Packet received, the HOST should be running transfer protocol before DEBUG_AGENT_REVISION. 1753 // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2. 1754 // 1755 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgVersionAlert, AsciiStrLen (mErrorMsgVersionAlert)); 1756 CpuDeadLoop (); 1757 } 1758 1759 if (RETURN_ERROR (Status)) { 1760 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectFail, AsciiStrLen (mErrorMsgConnectFail)); 1761 } else { 1762 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectOK, AsciiStrLen (mErrorMsgConnectOK)); 1763 // 1764 // Set Attach flag 1765 // 1766 SetHostAttached (TRUE); 1767 } 1768 return Status; 1769 } 1770 1771 /** 1772 Send Break point packet to HOST. 1773 1774 Only the first breaking processor could sent BREAK_POINT packet. 1775 1776 @param[in] BreakCause Break cause of this break event. 1777 @param[in] ProcessorIndex Processor index value. 1778 @param[out] BreakReceived If BreakReceived is not NULL, 1779 TRUE is retured if break-in symbol received. 1780 FALSE is retured if break-in symbol not received. 1781 1782 **/ 1783 VOID 1784 SendBreakPacketToHost ( 1785 IN UINT8 BreakCause, 1786 IN UINT32 ProcessorIndex, 1787 OUT BOOLEAN *BreakReceived 1788 ) 1789 { 1790 UINT8 InputCharacter; 1791 DEBUG_PORT_HANDLE Handle; 1792 1793 Handle = GetDebugPortHandle(); 1794 1795 if (IsHostAttached ()) { 1796 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex); 1797 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT, READ_PACKET_TIMEOUT, BreakReceived, NULL); 1798 } else { 1799 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Try to attach HOST.\n", ProcessorIndex); 1800 // 1801 // If HOST is not attached, try to attach it firstly. 1802 // 1803 // 1804 // Poll Attach symbols from HOST and ack OK 1805 // 1806 do { 1807 DebugAgentReadBuffer (Handle, &InputCharacter, 1, 0); 1808 } while (InputCharacter != DEBUG_STARTING_SYMBOL_ATTACH); 1809 SendAckPacket (DEBUG_COMMAND_OK); 1810 1811 // 1812 // Try to attach HOST 1813 // 1814 while (AttachHost (BreakCause, 0, NULL) != RETURN_SUCCESS); 1815 1816 } 1817 } 1818 1819 /** 1820 The main function to process communication with HOST. 1821 1822 It received the command packet from HOST, and sent response data packet to HOST. 1823 1824 @param[in] Vector Vector value of exception or interrutp. 1825 @param[in, out] CpuContext Pointer to saved CPU context. 1826 @param[in] BreakReceived TRUE means break-in symbol received. 1827 FALSE means break-in symbol not received. 1828 1829 **/ 1830 VOID 1831 CommandCommunication ( 1832 IN UINTN Vector, 1833 IN OUT DEBUG_CPU_CONTEXT *CpuContext, 1834 IN BOOLEAN BreakReceived 1835 ) 1836 { 1837 RETURN_STATUS Status; 1838 UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT + sizeof (UINT64) - 1]; 1839 DEBUG_PACKET_HEADER *DebugHeader; 1840 UINT8 Width; 1841 UINT8 Data8; 1842 UINT32 Data32; 1843 UINT64 Data64; 1844 DEBUG_DATA_READ_MEMORY *MemoryRead; 1845 DEBUG_DATA_WRITE_MEMORY *MemoryWrite; 1846 DEBUG_DATA_READ_IO *IoRead; 1847 DEBUG_DATA_WRITE_IO *IoWrite; 1848 DEBUG_DATA_READ_REGISTER *RegisterRead; 1849 DEBUG_DATA_WRITE_REGISTER *RegisterWrite; 1850 UINT8 *RegisterBuffer; 1851 DEBUG_DATA_READ_MSR *MsrRegisterRead; 1852 DEBUG_DATA_WRITE_MSR *MsrRegisterWrite; 1853 DEBUG_DATA_CPUID *Cpuid; 1854 DEBUG_DATA_RESPONSE_BREAK_CAUSE BreakCause; 1855 DEBUG_DATA_RESPONSE_CPUID CpuidResponse; 1856 DEBUG_DATA_SEARCH_SIGNATURE *SearchSignature; 1857 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception; 1858 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision; 1859 DEBUG_DATA_SET_VIEWPOINT *SetViewPoint; 1860 BOOLEAN HaltDeferred; 1861 UINT32 ProcessorIndex; 1862 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer; 1863 UINT32 IssuedViewPoint; 1864 DEBUG_AGENT_MAILBOX *Mailbox; 1865 UINT8 *AlignedDataPtr; 1866 1867 ProcessorIndex = 0; 1868 IssuedViewPoint = 0; 1869 HaltDeferred = BreakReceived; 1870 1871 if (MultiProcessorDebugSupport()) { 1872 ProcessorIndex = GetProcessorIndex (); 1873 SetCpuStopFlagByIndex (ProcessorIndex, TRUE); 1874 if (mDebugMpContext.ViewPointIndex == ProcessorIndex) { 1875 // 1876 // Only the current view processor could set AgentInProgress Flag. 1877 // 1878 IssuedViewPoint = ProcessorIndex; 1879 } 1880 } 1881 1882 if (IssuedViewPoint == ProcessorIndex) { 1883 // 1884 // Set AgentInProgress Flag. 1885 // 1886 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 1); 1887 } 1888 1889 while (TRUE) { 1890 1891 if (MultiProcessorDebugSupport()) { 1892 // 1893 // Check if the current processor is HOST view point 1894 // 1895 if (mDebugMpContext.ViewPointIndex != ProcessorIndex) { 1896 if (mDebugMpContext.RunCommandSet) { 1897 // 1898 // If HOST view point sets RUN flag, run GO command to leave 1899 // 1900 SetCpuStopFlagByIndex (ProcessorIndex, FALSE); 1901 CommandGo (CpuContext); 1902 break; 1903 } else { 1904 // 1905 // Run into loop again 1906 // 1907 CpuPause (); 1908 continue; 1909 } 1910 } 1911 } 1912 1913 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 1914 1915 DebugHeader =(DEBUG_PACKET_HEADER *) InputPacketBuffer; 1916 1917 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "TARGET: Try to get command from HOST...\n"); 1918 Status = ReceivePacket ((UINT8 *) DebugHeader, &BreakReceived, NULL, READ_PACKET_TIMEOUT, TRUE); 1919 if (Status != RETURN_SUCCESS || !IS_REQUEST (DebugHeader)) { 1920 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader->Command, DebugHeader->SequenceNo, Status); 1921 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command failed or it's response packet not expected! \n"); 1922 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 1923 continue; 1924 } 1925 1926 Mailbox = GetMailboxPointer (); 1927 if (DebugHeader->SequenceNo == Mailbox->HostSequenceNo) { 1928 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive one old command[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo); 1929 SendAckPacket (Mailbox->LastAck); 1930 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 1931 continue; 1932 } else if (DebugHeader->SequenceNo == (UINT8) (Mailbox->HostSequenceNo + 1)) { 1933 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8) DebugHeader->SequenceNo); 1934 } else { 1935 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Receive one invalid comamnd[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo); 1936 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 1937 continue; 1938 } 1939 1940 // 1941 // Save CPU content before executing HOST commond 1942 // 1943 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX, (UINT64)(UINTN) &AgentExceptionBuffer.JumpBuffer); 1944 if (SetJump (&AgentExceptionBuffer.JumpBuffer) != 0) { 1945 // 1946 // If HOST command failed, continue to wait for HOST's next command 1947 // If needed, agent could send exception info to HOST. 1948 // 1949 SendAckPacket (DEBUG_COMMAND_ABORT); 1950 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 1951 continue; 1952 } 1953 1954 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Processor[%x]:Received one command(%x)\n", mDebugMpContext.ViewPointIndex, DebugHeader->Command); 1955 1956 switch (DebugHeader->Command) { 1957 1958 case DEBUG_COMMAND_HALT: 1959 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED); 1960 HaltDeferred = TRUE; 1961 BreakReceived = FALSE; 1962 Status = RETURN_SUCCESS; 1963 break; 1964 1965 case DEBUG_COMMAND_RESET: 1966 SendAckPacket (DEBUG_COMMAND_OK); 1967 SendAckPacket (DEBUG_COMMAND_OK); 1968 SendAckPacket (DEBUG_COMMAND_OK); 1969 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 1970 1971 ResetCold (); 1972 // 1973 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet. 1974 // PCD can be used if 2 seconds isn't long enough for some platforms. 1975 // 1976 MicroSecondDelay (2000000); 1977 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, Mailbox->HostSequenceNo + 1); 1978 SendAckPacket (DEBUG_COMMAND_TIMEOUT); 1979 SendAckPacket (DEBUG_COMMAND_TIMEOUT); 1980 SendAckPacket (DEBUG_COMMAND_TIMEOUT); 1981 break; 1982 1983 case DEBUG_COMMAND_GO: 1984 CommandGo (CpuContext); 1985 // 1986 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO 1987 // If HOST changed Dr0 before GO, we will not change Dr0 here 1988 // 1989 Data8 = GetBreakCause (Vector, CpuContext); 1990 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) { 1991 CpuContext->Dr0 = 0; 1992 } 1993 1994 if (!HaltDeferred) { 1995 // 1996 // If no HALT command received when being in-active mode 1997 // 1998 if (MultiProcessorDebugSupport()) { 1999 Data32 = FindNextPendingBreakCpu (); 2000 if (Data32 != -1) { 2001 // 2002 // If there are still others processors being in break state, 2003 // send OK packet to HOST to finish this go command 2004 // 2005 SendAckPacket (DEBUG_COMMAND_OK); 2006 CpuPause (); 2007 // 2008 // Set current view to the next breaking processor 2009 // 2010 mDebugMpContext.ViewPointIndex = Data32; 2011 mDebugMpContext.BreakAtCpuIndex = mDebugMpContext.ViewPointIndex; 2012 SetCpuBreakFlagByIndex (mDebugMpContext.ViewPointIndex, FALSE); 2013 // 2014 // Send break packet to HOST to let HOST break again 2015 // 2016 SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN, mDebugMpContext.BreakAtCpuIndex, &BreakReceived); 2017 // 2018 // Continue to run into loop to read command packet from HOST 2019 // 2020 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 2021 break; 2022 } 2023 2024 // 2025 // If no else processor break, set stop bitmask, 2026 // and set Running flag for all processors. 2027 // 2028 SetCpuStopFlagByIndex (ProcessorIndex, FALSE); 2029 SetCpuRunningFlag (TRUE); 2030 CpuPause (); 2031 // 2032 // Wait for all processors are in running state 2033 // 2034 while (TRUE) { 2035 if (IsAllCpuRunning ()) { 2036 break; 2037 } 2038 } 2039 // 2040 // Set BSP to be current view point. 2041 // 2042 SetDebugViewPoint (mDebugMpContext.BspIndex); 2043 CpuPause (); 2044 // 2045 // Clear breaking processor index and running flag 2046 // 2047 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1); 2048 SetCpuRunningFlag (FALSE); 2049 } 2050 2051 // 2052 // Send OK packet to HOST to finish this go command 2053 // 2054 SendAckPacket (DEBUG_COMMAND_OK); 2055 2056 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 2057 2058 if (!IsHostAttached()) { 2059 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_SEQUENCE_NO_INDEX, 0); 2060 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, 0); 2061 } 2062 return; 2063 2064 } else { 2065 // 2066 // If reveived HALT command, need to defer the GO command 2067 // 2068 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED); 2069 HaltDeferred = FALSE; 2070 2071 Vector = DEBUG_TIMER_VECTOR; 2072 } 2073 break; 2074 2075 case DEBUG_COMMAND_BREAK_CAUSE: 2076 BreakCause.StopAddress = CpuContext->Eip; 2077 if (MultiProcessorDebugSupport() && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) { 2078 BreakCause.Cause = GetBreakCause (DEBUG_TIMER_VECTOR, CpuContext); 2079 } else { 2080 BreakCause.Cause = GetBreakCause (Vector, CpuContext); 2081 } 2082 SendDataResponsePacket ((UINT8 *) &BreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE), DebugHeader); 2083 break; 2084 2085 case DEBUG_COMMAND_SET_HW_BREAKPOINT: 2086 SetDebugRegister (CpuContext, (DEBUG_DATA_SET_HW_BREAKPOINT *) (DebugHeader + 1)); 2087 SendAckPacket (DEBUG_COMMAND_OK); 2088 break; 2089 2090 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT: 2091 ClearDebugRegister (CpuContext, (DEBUG_DATA_CLEAR_HW_BREAKPOINT *) (DebugHeader + 1)); 2092 SendAckPacket (DEBUG_COMMAND_OK); 2093 break; 2094 2095 case DEBUG_COMMAND_SINGLE_STEPPING: 2096 CommandStepping (CpuContext); 2097 // 2098 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO 2099 // If HOST changed Dr0 before GO, we will not change Dr0 here 2100 // 2101 Data8 = GetBreakCause (Vector, CpuContext); 2102 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) { 2103 CpuContext->Dr0 = 0; 2104 } 2105 2106 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1); 2107 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 2108 // 2109 // Executing stepping command directly without sending ACK packet, 2110 // ACK packet will be sent after stepping done. 2111 // 2112 return; 2113 2114 case DEBUG_COMMAND_SET_SW_BREAKPOINT: 2115 Data64 = (UINTN) (((DEBUG_DATA_SET_SW_BREAKPOINT *) (DebugHeader + 1))->Address); 2116 Data8 = *(UINT8 *) (UINTN) Data64; 2117 *(UINT8 *) (UINTN) Data64 = DEBUG_SW_BREAKPOINT_SYMBOL; 2118 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8), DebugHeader); 2119 break; 2120 2121 case DEBUG_COMMAND_READ_MEMORY: 2122 MemoryRead = (DEBUG_DATA_READ_MEMORY *) (DebugHeader + 1); 2123 Status = ReadMemoryAndSendResponsePacket ((UINT8 *) (UINTN) MemoryRead->Address, MemoryRead->Count, MemoryRead->Width, DebugHeader); 2124 break; 2125 2126 case DEBUG_COMMAND_WRITE_MEMORY: 2127 MemoryWrite = (DEBUG_DATA_WRITE_MEMORY *) (DebugHeader + 1); 2128 // 2129 // Copy data into one memory with 8-byte alignment address 2130 // 2131 AlignedDataPtr = ALIGN_POINTER ((UINT8 *) &MemoryWrite->Data, sizeof (UINT64)); 2132 if (AlignedDataPtr != (UINT8 *) &MemoryWrite->Data) { 2133 CopyMem (AlignedDataPtr, (UINT8 *) &MemoryWrite->Data, MemoryWrite->Count * MemoryWrite->Width); 2134 } 2135 CopyMemByWidth ((UINT8 *) (UINTN) MemoryWrite->Address, AlignedDataPtr, MemoryWrite->Count, MemoryWrite->Width); 2136 SendAckPacket (DEBUG_COMMAND_OK); 2137 break; 2138 2139 case DEBUG_COMMAND_READ_IO: 2140 IoRead = (DEBUG_DATA_READ_IO *) (DebugHeader + 1); 2141 switch (IoRead->Width) { 2142 case 1: 2143 Data64 = IoRead8 ((UINTN) IoRead->Port); 2144 break; 2145 case 2: 2146 Data64 = IoRead16 ((UINTN) IoRead->Port); 2147 break; 2148 case 4: 2149 Data64 = IoRead32 ((UINTN) IoRead->Port); 2150 break; 2151 case 8: 2152 Data64 = IoRead64 ((UINTN) IoRead->Port); 2153 break; 2154 default: 2155 Data64 = (UINT64) -1; 2156 } 2157 Status = SendDataResponsePacket ((UINT8 *) &Data64, IoRead->Width, DebugHeader); 2158 break; 2159 2160 case DEBUG_COMMAND_WRITE_IO: 2161 IoWrite = (DEBUG_DATA_WRITE_IO *) (DebugHeader + 1); 2162 switch (IoWrite->Width) { 2163 case 1: 2164 Data64 = IoWrite8 ((UINTN) IoWrite->Port, *(UINT8 *) &IoWrite->Data); 2165 break; 2166 case 2: 2167 Data64 = IoWrite16 ((UINTN) IoWrite->Port, *(UINT16 *) &IoWrite->Data); 2168 break; 2169 case 4: 2170 Data64 = IoWrite32 ((UINTN) IoWrite->Port, *(UINT32 *) &IoWrite->Data); 2171 break; 2172 case 8: 2173 Data64 = IoWrite64 ((UINTN) IoWrite->Port, *(UINT64 *) &IoWrite->Data); 2174 break; 2175 default: 2176 Data64 = (UINT64) -1; 2177 } 2178 SendAckPacket (DEBUG_COMMAND_OK); 2179 break; 2180 2181 case DEBUG_COMMAND_READ_ALL_REGISTERS: 2182 Status = SendDataResponsePacket ((UINT8 *) CpuContext, sizeof (*CpuContext), DebugHeader); 2183 break; 2184 2185 case DEBUG_COMMAND_READ_REGISTER: 2186 RegisterRead = (DEBUG_DATA_READ_REGISTER *) (DebugHeader + 1); 2187 2188 if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_MAX) { 2189 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, &Width); 2190 Status = SendDataResponsePacket (RegisterBuffer, Width, DebugHeader); 2191 } else { 2192 Status = RETURN_UNSUPPORTED; 2193 } 2194 break; 2195 2196 case DEBUG_COMMAND_WRITE_REGISTER: 2197 RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *) (DebugHeader + 1); 2198 if (RegisterWrite->Index <= SOFT_DEBUGGER_REGISTER_MAX) { 2199 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterWrite->Index, &Width); 2200 ASSERT (Width == RegisterWrite->Length); 2201 CopyMem (RegisterBuffer, RegisterWrite->Data, Width); 2202 SendAckPacket (DEBUG_COMMAND_OK); 2203 } else { 2204 Status = RETURN_UNSUPPORTED; 2205 } 2206 break; 2207 2208 case DEBUG_COMMAND_ARCH_MODE: 2209 Data8 = DEBUG_ARCH_SYMBOL; 2210 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8), DebugHeader); 2211 break; 2212 2213 case DEBUG_COMMAND_READ_MSR: 2214 MsrRegisterRead = (DEBUG_DATA_READ_MSR *) (DebugHeader + 1); 2215 Data64 = AsmReadMsr64 (MsrRegisterRead->Index); 2216 Status = SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (UINT64), DebugHeader); 2217 break; 2218 2219 case DEBUG_COMMAND_WRITE_MSR: 2220 MsrRegisterWrite = (DEBUG_DATA_WRITE_MSR *) (DebugHeader + 1); 2221 AsmWriteMsr64 (MsrRegisterWrite->Index, MsrRegisterWrite->Value); 2222 SendAckPacket (DEBUG_COMMAND_OK); 2223 break; 2224 2225 case DEBUG_COMMAND_SET_DEBUG_SETTING: 2226 Status = SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING *)(DebugHeader + 1)); 2227 if (Status == RETURN_SUCCESS) { 2228 SendAckPacket (DEBUG_COMMAND_OK); 2229 } 2230 break; 2231 2232 case DEBUG_COMMAND_GET_REVISION: 2233 DebugAgentRevision.Revision = DEBUG_AGENT_REVISION; 2234 DebugAgentRevision.Capabilities = DEBUG_AGENT_CAPABILITIES; 2235 Status = SendDataResponsePacket ((UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION), DebugHeader); 2236 break; 2237 2238 case DEBUG_COMMAND_GET_EXCEPTION: 2239 Exception.ExceptionNum = (UINT8) Vector; 2240 Exception.ExceptionData = (UINT32) CpuContext->ExceptionData; 2241 Status = SendDataResponsePacket ((UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION), DebugHeader); 2242 break; 2243 2244 case DEBUG_COMMAND_SET_VIEWPOINT: 2245 SetViewPoint = (DEBUG_DATA_SET_VIEWPOINT *) (DebugHeader + 1); 2246 if (MultiProcessorDebugSupport()) { 2247 if (IsCpuStopped (SetViewPoint->ViewPoint)) { 2248 SetDebugViewPoint (SetViewPoint->ViewPoint); 2249 SendAckPacket (DEBUG_COMMAND_OK); 2250 } else { 2251 // 2252 // If CPU is not halted 2253 // 2254 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED); 2255 } 2256 } else if (SetViewPoint->ViewPoint == 0) { 2257 SendAckPacket (DEBUG_COMMAND_OK); 2258 2259 } else { 2260 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED); 2261 } 2262 2263 break; 2264 2265 case DEBUG_COMMAND_GET_VIEWPOINT: 2266 Data32 = mDebugMpContext.ViewPointIndex; 2267 SendDataResponsePacket((UINT8 *) &Data32, (UINT16) sizeof (UINT32), DebugHeader); 2268 break; 2269 2270 case DEBUG_COMMAND_MEMORY_READY: 2271 Data8 = (UINT8) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY); 2272 SendDataResponsePacket (&Data8, (UINT16) sizeof (UINT8), DebugHeader); 2273 break; 2274 2275 case DEBUG_COMMAND_DETACH: 2276 SetHostAttached (FALSE); 2277 SendAckPacket (DEBUG_COMMAND_OK); 2278 break; 2279 2280 case DEBUG_COMMAND_CPUID: 2281 Cpuid = (DEBUG_DATA_CPUID *) (DebugHeader + 1); 2282 AsmCpuidEx ( 2283 Cpuid->Eax, Cpuid->Ecx, 2284 &CpuidResponse.Eax, &CpuidResponse.Ebx, 2285 &CpuidResponse.Ecx, &CpuidResponse.Edx 2286 ); 2287 SendDataResponsePacket ((UINT8 *) &CpuidResponse, (UINT16) sizeof (CpuidResponse), DebugHeader); 2288 break; 2289 2290 case DEBUG_COMMAND_SEARCH_SIGNATURE: 2291 SearchSignature = (DEBUG_DATA_SEARCH_SIGNATURE *) (DebugHeader + 1); 2292 if ((SearchSignature->Alignment != 0) && 2293 (SearchSignature->Alignment == GetPowerOfTwo32 (SearchSignature->Alignment)) 2294 ) { 2295 if (SearchSignature->Positive) { 2296 for ( 2297 Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start, SearchSignature->Alignment); 2298 Data64 <= SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength; 2299 Data64 += SearchSignature->Alignment 2300 ) { 2301 if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) { 2302 break; 2303 } 2304 } 2305 if (Data64 > SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength) { 2306 Data64 = (UINT64) -1; 2307 } 2308 } else { 2309 for ( 2310 Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start - SearchSignature->Alignment, SearchSignature->Alignment); 2311 Data64 >= SearchSignature->Start - SearchSignature->Count; 2312 Data64 -= SearchSignature->Alignment 2313 ) { 2314 if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) { 2315 break; 2316 } 2317 } 2318 if (Data64 < SearchSignature->Start - SearchSignature->Count) { 2319 Data64 = (UINT64) -1; 2320 } 2321 } 2322 SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (Data64), DebugHeader); 2323 } else { 2324 Status = RETURN_UNSUPPORTED; 2325 } 2326 break; 2327 2328 default: 2329 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED); 2330 break; 2331 } 2332 2333 if (Status == RETURN_UNSUPPORTED) { 2334 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED); 2335 } else if (Status != RETURN_SUCCESS) { 2336 SendAckPacket (DEBUG_COMMAND_ABORT); 2337 } 2338 2339 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 2340 CpuPause (); 2341 } 2342 } 2343 2344 /** 2345 C function called in interrupt handler. 2346 2347 @param[in] Vector Vector value of exception or interrutp. 2348 @param[in] CpuContext Pointer to save CPU context. 2349 2350 **/ 2351 VOID 2352 EFIAPI 2353 InterruptProcess ( 2354 IN UINT32 Vector, 2355 IN DEBUG_CPU_CONTEXT *CpuContext 2356 ) 2357 { 2358 UINT8 InputCharacter; 2359 UINT8 BreakCause; 2360 UINTN SavedEip; 2361 BOOLEAN BreakReceived; 2362 UINT32 ProcessorIndex; 2363 UINT32 CurrentDebugTimerInitCount; 2364 DEBUG_PORT_HANDLE Handle; 2365 UINT8 Data8; 2366 UINT8 *Al; 2367 UINT32 IssuedViewPoint; 2368 DEBUG_AGENT_EXCEPTION_BUFFER *ExceptionBuffer; 2369 2370 InputCharacter = 0; 2371 ProcessorIndex = 0; 2372 IssuedViewPoint = 0; 2373 BreakReceived = FALSE; 2374 2375 if (mSkipBreakpoint) { 2376 // 2377 // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM 2378 // 2379 if ((Vector == DEBUG_INT1_VECTOR) || (Vector == DEBUG_INT3_VECTOR)) { 2380 DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8 *) mWarningMsgIngoreBreakpoint, AsciiStrLen (mWarningMsgIngoreBreakpoint)); 2381 return; 2382 } 2383 } 2384 2385 if (MultiProcessorDebugSupport()) { 2386 ProcessorIndex = GetProcessorIndex (); 2387 // 2388 // If this processor has alreay halted before, need to check it later 2389 // 2390 if (IsCpuStopped (ProcessorIndex)) { 2391 IssuedViewPoint = ProcessorIndex; 2392 } 2393 } 2394 2395 if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) { 2396 // 2397 // Check if this exception is issued by Debug Agent itself 2398 // If yes, fill the debug agent exception buffer and LongJump() back to 2399 // the saved CPU content in CommandCommunication() 2400 // If exception is issued when executing Stepping, will be handled in 2401 // exception handle procedure. 2402 // 2403 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) { 2404 DebugAgentMsgPrint ( 2405 DEBUG_AGENT_ERROR, 2406 "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n", 2407 Vector, 2408 (UINTN)CpuContext->Eip 2409 ); 2410 ExceptionBuffer = (DEBUG_AGENT_EXCEPTION_BUFFER *) (UINTN) GetMailboxPointer()->ExceptionBufferPointer; 2411 ExceptionBuffer->ExceptionContent.ExceptionNum = (UINT8) Vector; 2412 ExceptionBuffer->ExceptionContent.ExceptionData = (UINT32) CpuContext->ExceptionData; 2413 LongJump ((BASE_LIBRARY_JUMP_BUFFER *)(UINTN)(ExceptionBuffer), 1); 2414 } 2415 } 2416 2417 if (MultiProcessorDebugSupport()) { 2418 // 2419 // If RUN commmand is executing, wait for it done. 2420 // 2421 while (mDebugMpContext.RunCommandSet) { 2422 CpuPause (); 2423 } 2424 } 2425 2426 Handle = GetDebugPortHandle(); 2427 BreakCause = GetBreakCause (Vector, CpuContext); 2428 switch (Vector) { 2429 case DEBUG_INT1_VECTOR: 2430 case DEBUG_INT3_VECTOR: 2431 switch (BreakCause) { 2432 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET: 2433 if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) { 2434 // 2435 // Try to connect HOST, return if fails 2436 // 2437 break; 2438 } 2439 CommandCommunication (Vector, CpuContext, BreakReceived); 2440 break; 2441 2442 case DEBUG_DATA_BREAK_CAUSE_STEPPING: 2443 // 2444 // Stepping is finished, send Ack package. 2445 // 2446 if (MultiProcessorDebugSupport()) { 2447 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex; 2448 } 2449 // 2450 // Clear Stepping Flag and restore EFLAGS.IF 2451 // 2452 CommandSteppingCleanup (CpuContext); 2453 SendAckPacket (DEBUG_COMMAND_OK); 2454 CommandCommunication (Vector, CpuContext, BreakReceived); 2455 break; 2456 2457 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY: 2458 // 2459 // Memory is ready 2460 // 2461 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY, READ_PACKET_TIMEOUT, &BreakReceived, NULL); 2462 CommandCommunication (Vector, CpuContext, BreakReceived); 2463 break; 2464 2465 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD: 2466 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD: 2467 // 2468 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE 2469 // 2470 Al = ArchReadRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, &Data8); 2471 *Al = DEBUG_AGENT_IMAGE_CONTINUE; 2472 2473 if (!IsHostAttached ()) { 2474 // 2475 // If HOST is not connected for image load/unload, return 2476 // 2477 break; 2478 } 2479 // 2480 // Continue to run the following common code 2481 // 2482 2483 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT: 2484 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT: 2485 default: 2486 // 2487 // Send Break packet to HOST 2488 // 2489 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 2490 // 2491 // Only the first breaking processor could send BREAK_POINT to HOST 2492 // 2493 if (IsFirstBreakProcessor (ProcessorIndex)) { 2494 SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived); 2495 } 2496 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 2497 2498 if (Vector == DEBUG_INT3_VECTOR) { 2499 // 2500 // go back address located "0xCC" 2501 // 2502 CpuContext->Eip--; 2503 SavedEip = CpuContext->Eip; 2504 CommandCommunication (Vector, CpuContext, BreakReceived); 2505 if ((SavedEip == CpuContext->Eip) && 2506 (*(UINT8 *) (UINTN) CpuContext->Eip == DEBUG_SW_BREAKPOINT_SYMBOL)) { 2507 // 2508 // If this is not a software breakpoint set by HOST, 2509 // restore EIP 2510 // 2511 CpuContext->Eip++; 2512 } 2513 } else { 2514 CommandCommunication (Vector, CpuContext, BreakReceived); 2515 } 2516 break; 2517 } 2518 2519 break; 2520 2521 case DEBUG_TIMER_VECTOR: 2522 2523 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 2524 2525 if (MultiProcessorDebugSupport()) { 2526 if (IsBsp (ProcessorIndex)) { 2527 // 2528 // If current processor is BSP, check Apic timer's init count if changed, 2529 // it may be re-written when switching BSP. 2530 // If it changed, re-initialize debug timer 2531 // 2532 CurrentDebugTimerInitCount = GetApicTimerInitCount (); 2533 if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) { 2534 InitializeDebugTimer (NULL, FALSE); 2535 SaveAndSetDebugTimerInterrupt (TRUE); 2536 } 2537 } 2538 2539 if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) { 2540 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 2541 // 2542 // If current processor is not BSP or this is one IPI sent by AP 2543 // 2544 if (mDebugMpContext.BreakAtCpuIndex != (UINT32) (-1)) { 2545 CommandCommunication (Vector, CpuContext, FALSE); 2546 } 2547 2548 // 2549 // Clear EOI before exiting interrupt process routine. 2550 // 2551 SendApicEoi (); 2552 break; 2553 } 2554 } 2555 2556 // 2557 // Only BSP could run here 2558 // 2559 while (TRUE) { 2560 // 2561 // If there is data in debug port, will check whether it is break(attach/break-in) symbol, 2562 // If yes, go into communication mode with HOST. 2563 // If no, exit interrupt process. 2564 // 2565 if (DebugReadBreakSymbol (Handle, &InputCharacter) == EFI_NOT_FOUND) { 2566 break; 2567 } 2568 2569 if ((!IsHostAttached () && (InputCharacter == DEBUG_STARTING_SYMBOL_ATTACH)) || 2570 (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_HALT)) || 2571 (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_GO)) 2572 ) { 2573 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE, "Received data [%02x]\n", InputCharacter); 2574 // 2575 // Ack OK for break-in symbol 2576 // 2577 SendAckPacket (DEBUG_COMMAND_OK); 2578 2579 // 2580 // If receive GO command in Debug Timer, means HOST may lost ACK packet before. 2581 // 2582 if (InputCharacter == DEBUG_COMMAND_GO) { 2583 break; 2584 } 2585 2586 if (!IsHostAttached ()) { 2587 // 2588 // Try to attach HOST, if no ack received after 200ms, return 2589 // 2590 if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) { 2591 break; 2592 } 2593 } 2594 2595 if (MultiProcessorDebugSupport()) { 2596 if(FindNextPendingBreakCpu () != -1) { 2597 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE); 2598 } else { 2599 HaltOtherProcessors (ProcessorIndex); 2600 } 2601 } 2602 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 2603 CommandCommunication (Vector, CpuContext, BreakReceived); 2604 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 2605 break; 2606 } 2607 } 2608 2609 // 2610 // Clear EOI before exiting interrupt process routine. 2611 // 2612 SendApicEoi (); 2613 2614 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 2615 2616 break; 2617 2618 default: 2619 if (Vector <= DEBUG_EXCEPT_SIMD) { 2620 DebugAgentMsgPrint ( 2621 DEBUG_AGENT_ERROR, 2622 "Exception happened, ExceptionNum is %d, EIP = 0x%x.\n", 2623 Vector, 2624 (UINTN) CpuContext->Eip 2625 ); 2626 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) { 2627 // 2628 // If exception happened when executing Stepping, send Ack package. 2629 // HOST consider Stepping command was finished. 2630 // 2631 if (MultiProcessorDebugSupport()) { 2632 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex; 2633 } 2634 // 2635 // Clear Stepping flag and restore EFLAGS.IF 2636 // 2637 CommandSteppingCleanup (CpuContext); 2638 SendAckPacket (DEBUG_COMMAND_OK); 2639 } else { 2640 // 2641 // Exception occurs, send Break packet to HOST 2642 // 2643 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 2644 // 2645 // Only the first breaking processor could send BREAK_POINT to HOST 2646 // 2647 if (IsFirstBreakProcessor (ProcessorIndex)) { 2648 SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived); 2649 } 2650 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock); 2651 } 2652 2653 CommandCommunication (Vector, CpuContext, BreakReceived); 2654 } 2655 break; 2656 } 2657 2658 if (MultiProcessorDebugSupport()) { 2659 // 2660 // Clear flag and wait for all processors run here 2661 // 2662 SetIpiSentByApFlag (FALSE); 2663 while (mDebugMpContext.RunCommandSet) { 2664 CpuPause (); 2665 } 2666 2667 // 2668 // Only current (view) processor could clean up AgentInProgress flag. 2669 // 2670 if (mDebugMpContext.ViewPointIndex == ProcessorIndex) { 2671 IssuedViewPoint = mDebugMpContext.ViewPointIndex; 2672 } 2673 } 2674 2675 if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) { 2676 // 2677 // If the command is not stepping, clean up AgentInProgress flag 2678 // 2679 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 0); 2680 } 2681 2682 return; 2683 } 2684 2685