• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
CalculateCrc16(IN UINT8 * Data,IN UINTN DataSize,IN UINT16 Crc)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
IsDebugAgentInitialzed(VOID)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
FindAndReportModuleImageInfo(IN UINTN AlignSize)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
TriggerSoftInterrupt(IN UINT32 Signature)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
UpdateMailboxChecksum(IN DEBUG_AGENT_MAILBOX * Mailbox)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
VerifyMailboxChecksum(IN DEBUG_AGENT_MAILBOX * Mailbox)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
UpdateMailboxContent(IN DEBUG_AGENT_MAILBOX * Mailbox,IN UINTN Index,IN UINT64 Value)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
DebugAgentReadBuffer(IN DEBUG_PORT_HANDLE Handle,IN UINT8 * Buffer,IN UINTN NumberOfBytes,IN UINTN Timeout)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
SetDebugFlag(IN UINT64 FlagMask,IN UINT32 FlagValue)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
GetDebugFlag(IN UINT64 FlagMask)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
SendDebugMsgPacket(IN CHAR8 * Buffer,IN UINTN Length)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
DebugAgentMsgPrint(IN UINT8 ErrorLevel,IN CHAR8 * Format,...)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
DebugAgentDataMsgPrint(IN UINT8 ErrorLevel,IN BOOLEAN IsSend,IN UINT8 * Data,IN UINT8 Length)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
ReadRemainingBreakPacket(IN DEBUG_PORT_HANDLE Handle,IN OUT DEBUG_PACKET_HEADER * DebugHeader)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
IsHostAttached(VOID)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
SetHostAttached(IN BOOLEAN Attached)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
SetDebugSetting(IN DEBUG_DATA_SET_DEBUG_SETTING * DebugSetting)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
CommandGo(IN DEBUG_CPU_CONTEXT * CpuContext)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
CommandStepping(IN DEBUG_CPU_CONTEXT * CpuContext)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
CommandSteppingCleanup(IN DEBUG_CPU_CONTEXT * CpuContext)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
SetDebugRegister(IN DEBUG_CPU_CONTEXT * CpuContext,IN DEBUG_DATA_SET_HW_BREAKPOINT * SetHwBreakpoint)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
ClearDebugRegister(IN DEBUG_CPU_CONTEXT * CpuContext,IN DEBUG_DATA_CLEAR_HW_BREAKPOINT * ClearHwBreakpoint)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
ArchReadFxStatOffset(IN UINT8 Index,OUT UINT8 * Width)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 *
ArchReadRegisterBuffer(IN DEBUG_CPU_CONTEXT * CpuContext,IN UINT8 Index,OUT UINT8 * Width)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
SendPacketWithoutData(IN UINT8 CommandType,IN UINT8 SequenceNo)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
SendAckPacket(IN UINT8 AckCommand)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
DecompressDataInPlace(IN OUT UINT8 * Data,IN UINTN Length)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
ReceivePacket(OUT UINT8 * InputPacket,OUT BOOLEAN * BreakReceived,OUT BOOLEAN * IncompatibilityFlag,OPTIONAL IN UINTN Timeout,IN BOOLEAN SkipStartSymbol)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
SendCommandAndWaitForAckOK(IN UINT8 Command,IN UINTN Timeout,OUT BOOLEAN * BreakReceived,OPTIONAL OUT BOOLEAN * IncompatibilityFlag OPTIONAL)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
GetBreakCause(IN UINTN Vector,IN DEBUG_CPU_CONTEXT * CpuContext)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
CopyMemByWidth(OUT UINT8 * Dest,IN UINT8 * Src,IN UINT16 Count,IN UINT8 Width)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
CompressData(IN DEBUG_PORT_HANDLE Handle,IN UINT8 * Data,IN UINT8 Length,IN BOOLEAN Send,OUT UINTN * CompressedLength,OPTIONAL OUT UINT16 * CompressedCrc OPTIONAL)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
ReadMemoryAndSendResponsePacket(IN UINT8 * Data,IN UINT16 Count,IN UINT8 Width,IN DEBUG_PACKET_HEADER * DebugHeader)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
SendDataResponsePacket(IN UINT8 * Data,IN UINT16 DataSize,IN OUT DEBUG_PACKET_HEADER * DebugHeader)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
AttachHost(IN UINT8 BreakCause,IN UINTN Timeout,OUT BOOLEAN * BreakReceived)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
SendBreakPacketToHost(IN UINT8 BreakCause,IN UINT32 ProcessorIndex,OUT BOOLEAN * BreakReceived)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
CommandCommunication(IN UINTN Vector,IN OUT DEBUG_CPU_CONTEXT * CpuContext,IN BOOLEAN BreakReceived)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
InterruptProcess(IN UINT32 Vector,IN DEBUG_CPU_CONTEXT * CpuContext)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