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_PORT_HANDLE                 Handle;
1863   DEBUG_AGENT_EXCEPTION_BUFFER      AgentExceptionBuffer;
1864   UINT32                            IssuedViewPoint;
1865   DEBUG_AGENT_MAILBOX               *Mailbox;
1866   UINT8                             *AlignedDataPtr;
1867 
1868   ProcessorIndex  = 0;
1869   IssuedViewPoint = 0;
1870   HaltDeferred    = BreakReceived;
1871 
1872   if (MultiProcessorDebugSupport()) {
1873     ProcessorIndex = GetProcessorIndex ();
1874     SetCpuStopFlagByIndex (ProcessorIndex, TRUE);
1875     if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {
1876       //
1877       // Only the current view processor could set AgentInProgress Flag.
1878       //
1879       IssuedViewPoint = ProcessorIndex;
1880     }
1881   }
1882 
1883   if (IssuedViewPoint == ProcessorIndex) {
1884     //
1885     // Set AgentInProgress Flag.
1886     //
1887     SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 1);
1888   }
1889 
1890   Handle = GetDebugPortHandle();
1891 
1892   while (TRUE) {
1893 
1894     if (MultiProcessorDebugSupport()) {
1895       //
1896       // Check if the current processor is HOST view point
1897       //
1898       if (mDebugMpContext.ViewPointIndex != ProcessorIndex) {
1899         if (mDebugMpContext.RunCommandSet) {
1900           //
1901           // If HOST view point sets RUN flag, run GO command to leave
1902           //
1903           SetCpuStopFlagByIndex (ProcessorIndex, FALSE);
1904           CommandGo (CpuContext);
1905           break;
1906         } else {
1907           //
1908           // Run into loop again
1909           //
1910           CpuPause ();
1911           continue;
1912         }
1913       }
1914     }
1915 
1916     AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
1917 
1918     DebugHeader =(DEBUG_PACKET_HEADER *) InputPacketBuffer;
1919 
1920     DebugAgentMsgPrint (DEBUG_AGENT_INFO, "TARGET: Try to get command from HOST...\n");
1921     Status = ReceivePacket ((UINT8 *) DebugHeader, &BreakReceived, NULL, READ_PACKET_TIMEOUT, TRUE);
1922     if (Status != RETURN_SUCCESS || !IS_REQUEST (DebugHeader)) {
1923       DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader->Command, DebugHeader->SequenceNo, Status);
1924       DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command failed or it's response packet not expected! \n");
1925       ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
1926       continue;
1927     }
1928 
1929     Mailbox = GetMailboxPointer ();
1930     if (DebugHeader->SequenceNo == Mailbox->HostSequenceNo) {
1931       DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive one old command[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);
1932       SendAckPacket (Mailbox->LastAck);
1933       ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
1934       continue;
1935     } else if (DebugHeader->SequenceNo == (UINT8) (Mailbox->HostSequenceNo + 1)) {
1936       UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8) DebugHeader->SequenceNo);
1937     } else {
1938       DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Receive one invalid comamnd[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);
1939       ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
1940       continue;
1941     }
1942 
1943     //
1944     // Save CPU content before executing HOST commond
1945     //
1946     UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX, (UINT64)(UINTN) &AgentExceptionBuffer.JumpBuffer);
1947     if (SetJump (&AgentExceptionBuffer.JumpBuffer) != 0) {
1948       //
1949       // If HOST command failed, continue to wait for HOST's next command
1950       // If needed, agent could send exception info to HOST.
1951       //
1952       SendAckPacket (DEBUG_COMMAND_ABORT);
1953       ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
1954       continue;
1955     }
1956 
1957     DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Processor[%x]:Received one command(%x)\n", mDebugMpContext.ViewPointIndex, DebugHeader->Command);
1958 
1959     switch (DebugHeader->Command) {
1960 
1961     case DEBUG_COMMAND_HALT:
1962       SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);
1963       HaltDeferred = TRUE;
1964       BreakReceived = FALSE;
1965       Status = RETURN_SUCCESS;
1966       break;
1967 
1968     case DEBUG_COMMAND_RESET:
1969       SendAckPacket (DEBUG_COMMAND_OK);
1970       SendAckPacket (DEBUG_COMMAND_OK);
1971       SendAckPacket (DEBUG_COMMAND_OK);
1972       ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
1973 
1974       ResetCold ();
1975       //
1976       // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.
1977       // PCD can be used if 2 seconds isn't long enough for some platforms.
1978       //
1979       MicroSecondDelay (2000000);
1980       UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, Mailbox->HostSequenceNo + 1);
1981       SendAckPacket (DEBUG_COMMAND_TIMEOUT);
1982       SendAckPacket (DEBUG_COMMAND_TIMEOUT);
1983       SendAckPacket (DEBUG_COMMAND_TIMEOUT);
1984       break;
1985 
1986     case DEBUG_COMMAND_GO:
1987       CommandGo (CpuContext);
1988       //
1989       // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1990       // If HOST changed Dr0 before GO, we will not change Dr0 here
1991       //
1992       Data8 = GetBreakCause (Vector, CpuContext);
1993       if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {
1994         CpuContext->Dr0 = 0;
1995       }
1996 
1997       if (!HaltDeferred) {
1998         //
1999         // If no HALT command received when being in-active mode
2000         //
2001         if (MultiProcessorDebugSupport()) {
2002           Data32 = FindNextPendingBreakCpu ();
2003           if (Data32 != -1) {
2004             //
2005             // If there are still others processors being in break state,
2006             // send OK packet to HOST to finish this go command
2007             //
2008             SendAckPacket (DEBUG_COMMAND_OK);
2009             CpuPause ();
2010             //
2011             // Set current view to the next breaking processor
2012             //
2013             mDebugMpContext.ViewPointIndex = Data32;
2014             mDebugMpContext.BreakAtCpuIndex = mDebugMpContext.ViewPointIndex;
2015             SetCpuBreakFlagByIndex (mDebugMpContext.ViewPointIndex, FALSE);
2016             //
2017             // Send break packet to HOST to let HOST break again
2018             //
2019             SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN, mDebugMpContext.BreakAtCpuIndex, &BreakReceived);
2020             //
2021             // Continue to run into loop to read command packet from HOST
2022             //
2023             ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2024             break;
2025           }
2026 
2027           //
2028           // If no else processor break, set stop bitmask,
2029           // and set Running flag for all processors.
2030           //
2031           SetCpuStopFlagByIndex (ProcessorIndex, FALSE);
2032           SetCpuRunningFlag (TRUE);
2033           CpuPause ();
2034           //
2035           // Wait for all processors are in running state
2036           //
2037           while (TRUE) {
2038             if (IsAllCpuRunning ()) {
2039               break;
2040             }
2041           }
2042           //
2043           // Set BSP to be current view point.
2044           //
2045           SetDebugViewPoint (mDebugMpContext.BspIndex);
2046           CpuPause ();
2047           //
2048           // Clear breaking processor index and running flag
2049           //
2050           mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);
2051           SetCpuRunningFlag (FALSE);
2052         }
2053 
2054         //
2055         // Send OK packet to HOST to finish this go command
2056         //
2057         SendAckPacket (DEBUG_COMMAND_OK);
2058 
2059         ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2060 
2061         if (!IsHostAttached()) {
2062           UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_SEQUENCE_NO_INDEX, 0);
2063           UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, 0);
2064         }
2065         return;
2066 
2067       } else {
2068         //
2069         // If reveived HALT command, need to defer the GO command
2070         //
2071         SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED);
2072         HaltDeferred = FALSE;
2073 
2074         Vector = DEBUG_TIMER_VECTOR;
2075       }
2076       break;
2077 
2078     case DEBUG_COMMAND_BREAK_CAUSE:
2079       BreakCause.StopAddress = CpuContext->Eip;
2080       if (MultiProcessorDebugSupport() && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {
2081         BreakCause.Cause       = GetBreakCause (DEBUG_TIMER_VECTOR, CpuContext);
2082       } else {
2083         BreakCause.Cause       = GetBreakCause (Vector, CpuContext);
2084       }
2085       SendDataResponsePacket ((UINT8 *) &BreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE), DebugHeader);
2086       break;
2087 
2088     case DEBUG_COMMAND_SET_HW_BREAKPOINT:
2089       SetDebugRegister (CpuContext, (DEBUG_DATA_SET_HW_BREAKPOINT *) (DebugHeader + 1));
2090       SendAckPacket (DEBUG_COMMAND_OK);
2091       break;
2092 
2093     case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT:
2094       ClearDebugRegister (CpuContext, (DEBUG_DATA_CLEAR_HW_BREAKPOINT *) (DebugHeader + 1));
2095       SendAckPacket (DEBUG_COMMAND_OK);
2096       break;
2097 
2098     case DEBUG_COMMAND_SINGLE_STEPPING:
2099       CommandStepping (CpuContext);
2100       //
2101       // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
2102       // If HOST changed Dr0 before GO, we will not change Dr0 here
2103       //
2104       Data8 = GetBreakCause (Vector, CpuContext);
2105       if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {
2106         CpuContext->Dr0 = 0;
2107       }
2108 
2109       mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);
2110       ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2111       //
2112       // Executing stepping command directly without sending ACK packet,
2113       // ACK packet will be sent after stepping done.
2114       //
2115       return;
2116 
2117     case DEBUG_COMMAND_SET_SW_BREAKPOINT:
2118       Data64 = (UINTN) (((DEBUG_DATA_SET_SW_BREAKPOINT *) (DebugHeader + 1))->Address);
2119       Data8 = *(UINT8 *) (UINTN) Data64;
2120       *(UINT8 *) (UINTN) Data64 = DEBUG_SW_BREAKPOINT_SYMBOL;
2121       Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8), DebugHeader);
2122       break;
2123 
2124     case DEBUG_COMMAND_READ_MEMORY:
2125       MemoryRead = (DEBUG_DATA_READ_MEMORY *) (DebugHeader + 1);
2126       Status = ReadMemoryAndSendResponsePacket ((UINT8 *) (UINTN) MemoryRead->Address, MemoryRead->Count, MemoryRead->Width, DebugHeader);
2127       break;
2128 
2129     case DEBUG_COMMAND_WRITE_MEMORY:
2130       MemoryWrite = (DEBUG_DATA_WRITE_MEMORY *) (DebugHeader + 1);
2131       //
2132       // Copy data into one memory with 8-byte alignment address
2133       //
2134       AlignedDataPtr = ALIGN_POINTER ((UINT8 *) &MemoryWrite->Data, sizeof (UINT64));
2135       if (AlignedDataPtr != (UINT8 *) &MemoryWrite->Data) {
2136         CopyMem (AlignedDataPtr, (UINT8 *) &MemoryWrite->Data, MemoryWrite->Count * MemoryWrite->Width);
2137       }
2138       CopyMemByWidth ((UINT8 *) (UINTN) MemoryWrite->Address, AlignedDataPtr, MemoryWrite->Count, MemoryWrite->Width);
2139       SendAckPacket (DEBUG_COMMAND_OK);
2140       break;
2141 
2142     case DEBUG_COMMAND_READ_IO:
2143       IoRead = (DEBUG_DATA_READ_IO *) (DebugHeader + 1);
2144       switch (IoRead->Width) {
2145       case 1:
2146         Data64  = IoRead8 ((UINTN) IoRead->Port);
2147         break;
2148       case 2:
2149         Data64  = IoRead16 ((UINTN) IoRead->Port);
2150         break;
2151       case 4:
2152         Data64  = IoRead32 ((UINTN) IoRead->Port);
2153         break;
2154       case 8:
2155         Data64  = IoRead64 ((UINTN) IoRead->Port);
2156         break;
2157       default:
2158         Data64  = (UINT64) -1;
2159       }
2160       Status = SendDataResponsePacket ((UINT8 *) &Data64, IoRead->Width, DebugHeader);
2161       break;
2162 
2163     case DEBUG_COMMAND_WRITE_IO:
2164       IoWrite = (DEBUG_DATA_WRITE_IO *) (DebugHeader + 1);
2165       switch (IoWrite->Width) {
2166       case 1:
2167         Data64  = IoWrite8 ((UINTN) IoWrite->Port, *(UINT8 *) &IoWrite->Data);
2168         break;
2169       case 2:
2170         Data64  = IoWrite16 ((UINTN) IoWrite->Port, *(UINT16 *) &IoWrite->Data);
2171         break;
2172       case 4:
2173         Data64  = IoWrite32 ((UINTN) IoWrite->Port, *(UINT32 *) &IoWrite->Data);
2174         break;
2175       case 8:
2176         Data64  = IoWrite64 ((UINTN) IoWrite->Port, *(UINT64 *) &IoWrite->Data);
2177         break;
2178       default:
2179         Data64  = (UINT64) -1;
2180       }
2181       SendAckPacket (DEBUG_COMMAND_OK);
2182       break;
2183 
2184     case DEBUG_COMMAND_READ_ALL_REGISTERS:
2185       Status = SendDataResponsePacket ((UINT8 *) CpuContext, sizeof (*CpuContext), DebugHeader);
2186       break;
2187 
2188     case DEBUG_COMMAND_READ_REGISTER:
2189       RegisterRead = (DEBUG_DATA_READ_REGISTER *) (DebugHeader + 1);
2190 
2191       if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_MAX) {
2192         RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, &Width);
2193         Status = SendDataResponsePacket (RegisterBuffer, Width, DebugHeader);
2194       } else {
2195         Status = RETURN_UNSUPPORTED;
2196       }
2197       break;
2198 
2199     case DEBUG_COMMAND_WRITE_REGISTER:
2200       RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *) (DebugHeader + 1);
2201       if (RegisterWrite->Index <= SOFT_DEBUGGER_REGISTER_MAX) {
2202         RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterWrite->Index, &Width);
2203         ASSERT (Width == RegisterWrite->Length);
2204         CopyMem (RegisterBuffer, RegisterWrite->Data, Width);
2205         SendAckPacket (DEBUG_COMMAND_OK);
2206       } else {
2207         Status = RETURN_UNSUPPORTED;
2208       }
2209       break;
2210 
2211     case DEBUG_COMMAND_ARCH_MODE:
2212       Data8 = DEBUG_ARCH_SYMBOL;
2213       Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8), DebugHeader);
2214       break;
2215 
2216     case DEBUG_COMMAND_READ_MSR:
2217       MsrRegisterRead = (DEBUG_DATA_READ_MSR *) (DebugHeader + 1);
2218       Data64 = AsmReadMsr64 (MsrRegisterRead->Index);
2219       Status = SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (UINT64), DebugHeader);
2220       break;
2221 
2222     case DEBUG_COMMAND_WRITE_MSR:
2223       MsrRegisterWrite = (DEBUG_DATA_WRITE_MSR *) (DebugHeader + 1);
2224       AsmWriteMsr64 (MsrRegisterWrite->Index, MsrRegisterWrite->Value);
2225       SendAckPacket (DEBUG_COMMAND_OK);
2226       break;
2227 
2228     case DEBUG_COMMAND_SET_DEBUG_SETTING:
2229       Status = SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING *)(DebugHeader + 1));
2230       if (Status == RETURN_SUCCESS) {
2231         SendAckPacket (DEBUG_COMMAND_OK);
2232       }
2233       break;
2234 
2235     case DEBUG_COMMAND_GET_REVISION:
2236       DebugAgentRevision.Revision = DEBUG_AGENT_REVISION;
2237       DebugAgentRevision.Capabilities = DEBUG_AGENT_CAPABILITIES;
2238       Status = SendDataResponsePacket ((UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION), DebugHeader);
2239       break;
2240 
2241     case DEBUG_COMMAND_GET_EXCEPTION:
2242       Exception.ExceptionNum  = (UINT8) Vector;
2243       Exception.ExceptionData = (UINT32) CpuContext->ExceptionData;
2244       Status = SendDataResponsePacket ((UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION), DebugHeader);
2245       break;
2246 
2247     case DEBUG_COMMAND_SET_VIEWPOINT:
2248       SetViewPoint = (DEBUG_DATA_SET_VIEWPOINT *) (DebugHeader + 1);
2249       if (MultiProcessorDebugSupport()) {
2250         if (IsCpuStopped (SetViewPoint->ViewPoint)) {
2251           SetDebugViewPoint (SetViewPoint->ViewPoint);
2252           SendAckPacket (DEBUG_COMMAND_OK);
2253         } else {
2254           //
2255           // If CPU is not halted
2256           //
2257           SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
2258         }
2259       } else if (SetViewPoint->ViewPoint == 0) {
2260         SendAckPacket (DEBUG_COMMAND_OK);
2261 
2262       } else {
2263         SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
2264       }
2265 
2266       break;
2267 
2268     case DEBUG_COMMAND_GET_VIEWPOINT:
2269       Data32 = mDebugMpContext.ViewPointIndex;
2270       SendDataResponsePacket((UINT8 *) &Data32, (UINT16) sizeof (UINT32), DebugHeader);
2271       break;
2272 
2273     case DEBUG_COMMAND_MEMORY_READY:
2274       Data8 = (UINT8) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY);
2275       SendDataResponsePacket (&Data8, (UINT16) sizeof (UINT8), DebugHeader);
2276       break;
2277 
2278     case DEBUG_COMMAND_DETACH:
2279       SetHostAttached (FALSE);
2280       SendAckPacket (DEBUG_COMMAND_OK);
2281       break;
2282 
2283     case DEBUG_COMMAND_CPUID:
2284       Cpuid = (DEBUG_DATA_CPUID *) (DebugHeader + 1);
2285       AsmCpuidEx (
2286         Cpuid->Eax, Cpuid->Ecx,
2287         &CpuidResponse.Eax, &CpuidResponse.Ebx,
2288         &CpuidResponse.Ecx, &CpuidResponse.Edx
2289         );
2290       SendDataResponsePacket ((UINT8 *) &CpuidResponse, (UINT16) sizeof (CpuidResponse), DebugHeader);
2291       break;
2292 
2293    case DEBUG_COMMAND_SEARCH_SIGNATURE:
2294       SearchSignature = (DEBUG_DATA_SEARCH_SIGNATURE *) (DebugHeader + 1);
2295       if ((SearchSignature->Alignment != 0) &&
2296           (SearchSignature->Alignment == GetPowerOfTwo32 (SearchSignature->Alignment))
2297          ) {
2298         if (SearchSignature->Positive) {
2299           for (
2300             Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start, SearchSignature->Alignment);
2301             Data64 <= SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength;
2302             Data64 += SearchSignature->Alignment
2303               ) {
2304             if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {
2305               break;
2306             }
2307           }
2308           if (Data64 > SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength) {
2309             Data64 = (UINT64) -1;
2310           }
2311         } else {
2312           for (
2313             Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start - SearchSignature->Alignment, SearchSignature->Alignment);
2314             Data64 >= SearchSignature->Start - SearchSignature->Count;
2315             Data64 -= SearchSignature->Alignment
2316               ) {
2317             if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {
2318               break;
2319             }
2320           }
2321           if (Data64 < SearchSignature->Start - SearchSignature->Count) {
2322             Data64 = (UINT64) -1;
2323           }
2324         }
2325         SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (Data64), DebugHeader);
2326       } else {
2327         Status = RETURN_UNSUPPORTED;
2328       }
2329       break;
2330 
2331     default:
2332       SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
2333       break;
2334     }
2335 
2336     if (Status == RETURN_UNSUPPORTED) {
2337       SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
2338     } else if (Status != RETURN_SUCCESS) {
2339       SendAckPacket (DEBUG_COMMAND_ABORT);
2340     }
2341 
2342     ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2343     CpuPause ();
2344   }
2345 }
2346 
2347 /**
2348   C function called in interrupt handler.
2349 
2350   @param[in] Vector      Vector value of exception or interrutp.
2351   @param[in] CpuContext  Pointer to save CPU context.
2352 
2353 **/
2354 VOID
2355 EFIAPI
InterruptProcess(IN UINT32 Vector,IN DEBUG_CPU_CONTEXT * CpuContext)2356 InterruptProcess (
2357   IN UINT32                          Vector,
2358   IN DEBUG_CPU_CONTEXT               *CpuContext
2359   )
2360 {
2361   UINT8                            InputCharacter;
2362   UINT8                            BreakCause;
2363   UINTN                            SavedEip;
2364   BOOLEAN                          BreakReceived;
2365   UINT32                           ProcessorIndex;
2366   UINT32                           CurrentDebugTimerInitCount;
2367   DEBUG_PORT_HANDLE                Handle;
2368   UINT8                            Data8;
2369   UINT8                            *Al;
2370   UINT32                           IssuedViewPoint;
2371   DEBUG_AGENT_EXCEPTION_BUFFER     *ExceptionBuffer;
2372 
2373   InputCharacter  = 0;
2374   ProcessorIndex  = 0;
2375   IssuedViewPoint = 0;
2376   BreakReceived   = FALSE;
2377 
2378   if (mSkipBreakpoint) {
2379     //
2380     // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM
2381     //
2382     if ((Vector == DEBUG_INT1_VECTOR) || (Vector == DEBUG_INT3_VECTOR)) {
2383       DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8 *) mWarningMsgIngoreBreakpoint, AsciiStrLen (mWarningMsgIngoreBreakpoint));
2384       return;
2385     }
2386   }
2387 
2388   if (MultiProcessorDebugSupport()) {
2389     ProcessorIndex = GetProcessorIndex ();
2390     //
2391     // If this processor has alreay halted before, need to check it later
2392     //
2393     if (IsCpuStopped (ProcessorIndex)) {
2394       IssuedViewPoint = ProcessorIndex;
2395     }
2396   }
2397 
2398   if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {
2399     //
2400     // Check if this exception is issued by Debug Agent itself
2401     // If yes, fill the debug agent exception buffer and LongJump() back to
2402     // the saved CPU content in CommandCommunication()
2403     // If exception is issued when executing Stepping, will be handled in
2404     // exception handle procedure.
2405     //
2406     if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) {
2407       DebugAgentMsgPrint (
2408         DEBUG_AGENT_ERROR,
2409         "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n",
2410         Vector,
2411         (UINTN)CpuContext->Eip
2412         );
2413       ExceptionBuffer = (DEBUG_AGENT_EXCEPTION_BUFFER *) (UINTN) GetMailboxPointer()->ExceptionBufferPointer;
2414       ExceptionBuffer->ExceptionContent.ExceptionNum  = (UINT8) Vector;
2415       ExceptionBuffer->ExceptionContent.ExceptionData = (UINT32) CpuContext->ExceptionData;
2416       LongJump ((BASE_LIBRARY_JUMP_BUFFER *)(UINTN)(ExceptionBuffer), 1);
2417     }
2418   }
2419 
2420   if (MultiProcessorDebugSupport()) {
2421     //
2422     // If RUN commmand is executing, wait for it done.
2423     //
2424     while (mDebugMpContext.RunCommandSet) {
2425       CpuPause ();
2426     }
2427   }
2428 
2429   Handle     = GetDebugPortHandle();
2430   BreakCause = GetBreakCause (Vector, CpuContext);
2431   switch (Vector) {
2432   case DEBUG_INT1_VECTOR:
2433   case DEBUG_INT3_VECTOR:
2434     switch (BreakCause) {
2435     case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET:
2436       if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {
2437         //
2438         // Try to connect HOST, return if fails
2439         //
2440         break;
2441       }
2442       CommandCommunication (Vector, CpuContext, BreakReceived);
2443       break;
2444 
2445     case DEBUG_DATA_BREAK_CAUSE_STEPPING:
2446       //
2447       // Stepping is finished, send Ack package.
2448       //
2449       if (MultiProcessorDebugSupport()) {
2450         mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;
2451       }
2452       //
2453       // Clear Stepping Flag and restore EFLAGS.IF
2454       //
2455       CommandSteppingCleanup (CpuContext);
2456       SendAckPacket (DEBUG_COMMAND_OK);
2457       CommandCommunication (Vector, CpuContext, BreakReceived);
2458       break;
2459 
2460     case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY:
2461       //
2462       // Memory is ready
2463       //
2464       SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY, READ_PACKET_TIMEOUT, &BreakReceived, NULL);
2465       CommandCommunication (Vector, CpuContext, BreakReceived);
2466       break;
2467 
2468     case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD:
2469     case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD:
2470       //
2471       // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
2472       //
2473       Al = ArchReadRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, &Data8);
2474       *Al = DEBUG_AGENT_IMAGE_CONTINUE;
2475 
2476       if (!IsHostAttached ()) {
2477         //
2478         // If HOST is not connected for image load/unload, return
2479         //
2480         break;
2481       }
2482       //
2483       // Continue to run the following common code
2484       //
2485 
2486     case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT:
2487     case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT:
2488     default:
2489       //
2490       // Send Break packet to HOST
2491       //
2492       AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2493       //
2494       // Only the first breaking processor could send BREAK_POINT to HOST
2495       //
2496       if (IsFirstBreakProcessor (ProcessorIndex)) {
2497         SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);
2498       }
2499       ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2500 
2501       if (Vector == DEBUG_INT3_VECTOR) {
2502         //
2503         // go back address located "0xCC"
2504         //
2505         CpuContext->Eip--;
2506         SavedEip = CpuContext->Eip;
2507         CommandCommunication (Vector, CpuContext, BreakReceived);
2508         if ((SavedEip == CpuContext->Eip) &&
2509             (*(UINT8 *) (UINTN) CpuContext->Eip == DEBUG_SW_BREAKPOINT_SYMBOL)) {
2510           //
2511           // If this is not a software breakpoint set by HOST,
2512           // restore EIP
2513           //
2514           CpuContext->Eip++;
2515         }
2516       } else {
2517         CommandCommunication (Vector, CpuContext, BreakReceived);
2518       }
2519       break;
2520     }
2521 
2522     break;
2523 
2524   case DEBUG_TIMER_VECTOR:
2525 
2526     AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2527 
2528     if (MultiProcessorDebugSupport()) {
2529       if (IsBsp (ProcessorIndex)) {
2530         //
2531         // If current processor is BSP, check Apic timer's init count if changed,
2532         // it may be re-written when switching BSP.
2533         // If it changed, re-initialize debug timer
2534         //
2535         CurrentDebugTimerInitCount = GetApicTimerInitCount ();
2536         if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {
2537           InitializeDebugTimer (NULL, FALSE);
2538           SaveAndSetDebugTimerInterrupt (TRUE);
2539         }
2540       }
2541 
2542       if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {
2543         ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2544         //
2545         // If current processor is not BSP or this is one IPI sent by AP
2546         //
2547         if (mDebugMpContext.BreakAtCpuIndex != (UINT32) (-1)) {
2548           CommandCommunication (Vector, CpuContext, FALSE);
2549         }
2550 
2551         //
2552         // Clear EOI before exiting interrupt process routine.
2553         //
2554         SendApicEoi ();
2555         break;
2556       }
2557     }
2558 
2559     //
2560     // Only BSP could run here
2561     //
2562     while (TRUE) {
2563       //
2564       // If there is data in debug port, will check whether it is break(attach/break-in) symbol,
2565       // If yes, go into communication mode with HOST.
2566       // If no, exit interrupt process.
2567       //
2568       if (DebugReadBreakSymbol (Handle, &InputCharacter) == EFI_NOT_FOUND) {
2569         break;
2570       }
2571 
2572       if ((!IsHostAttached () && (InputCharacter == DEBUG_STARTING_SYMBOL_ATTACH)) ||
2573           (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_HALT)) ||
2574           (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_GO))
2575          ) {
2576         DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE, "Received data [%02x]\n", InputCharacter);
2577         //
2578         // Ack OK for break-in symbol
2579         //
2580         SendAckPacket (DEBUG_COMMAND_OK);
2581 
2582         //
2583         // If receive GO command in Debug Timer, means HOST may lost ACK packet before.
2584         //
2585         if (InputCharacter == DEBUG_COMMAND_GO) {
2586           break;
2587         }
2588 
2589         if (!IsHostAttached ()) {
2590           //
2591           // Try to attach HOST, if no ack received after 200ms, return
2592           //
2593           if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {
2594             break;
2595           }
2596         }
2597 
2598         if (MultiProcessorDebugSupport()) {
2599           if(FindNextPendingBreakCpu  () != -1) {
2600             SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
2601           } else {
2602             HaltOtherProcessors (ProcessorIndex);
2603           }
2604         }
2605         ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2606         CommandCommunication (Vector, CpuContext, BreakReceived);
2607         AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2608         break;
2609       }
2610     }
2611 
2612     //
2613     // Clear EOI before exiting interrupt process routine.
2614     //
2615     SendApicEoi ();
2616 
2617     ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2618 
2619     break;
2620 
2621   default:
2622     if (Vector <= DEBUG_EXCEPT_SIMD) {
2623       DebugAgentMsgPrint (
2624         DEBUG_AGENT_ERROR,
2625         "Exception happened, ExceptionNum is %d, EIP = 0x%x.\n",
2626         Vector,
2627         (UINTN) CpuContext->Eip
2628         );
2629       if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {
2630         //
2631         // If exception happened when executing Stepping, send Ack package.
2632         // HOST consider Stepping command was finished.
2633         //
2634         if (MultiProcessorDebugSupport()) {
2635           mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;
2636         }
2637         //
2638         // Clear Stepping flag and restore EFLAGS.IF
2639         //
2640         CommandSteppingCleanup (CpuContext);
2641         SendAckPacket (DEBUG_COMMAND_OK);
2642       } else {
2643         //
2644         // Exception occurs, send Break packet to HOST
2645         //
2646         AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2647         //
2648         // Only the first breaking processor could send BREAK_POINT to HOST
2649         //
2650         if (IsFirstBreakProcessor (ProcessorIndex)) {
2651           SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);
2652         }
2653         ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2654       }
2655 
2656       CommandCommunication (Vector, CpuContext, BreakReceived);
2657     }
2658     break;
2659   }
2660 
2661   if (MultiProcessorDebugSupport()) {
2662     //
2663     // Clear flag and wait for all processors run here
2664     //
2665     SetIpiSentByApFlag (FALSE);
2666     while (mDebugMpContext.RunCommandSet) {
2667       CpuPause ();
2668     }
2669 
2670     //
2671     // Only current (view) processor could clean up AgentInProgress flag.
2672     //
2673     if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {
2674       IssuedViewPoint = mDebugMpContext.ViewPointIndex;
2675     }
2676   }
2677 
2678   if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {
2679     //
2680     // If the command is not stepping, clean up AgentInProgress flag
2681     //
2682     SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 0);
2683   }
2684 
2685   return;
2686 }
2687 
2688