Home | History | Annotate | Download | only in DebugAgentCommon
      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